From b06dc172319fbc2082c1e6b26ccd99f592f72de9 Mon Sep 17 00:00:00 2001 From: rtyag Date: Tue, 28 Jan 2025 12:33:30 +1100 Subject: [PATCH 01/43] SR BASOP ivas decoder and apps, not compiling yet --- Workspace_msvc/isar_post_rend.vcxproj | 179 + Workspace_msvc/lib_isar.vcxproj | 202 + Workspace_msvc/lib_lc3plus.vcxproj | 195 + apps/decoder.c | 485 +- apps/isar_post_rend.c | 1262 ++ apps/renderer.c | 553 +- lib_com/cldfb.c | 1 - lib_com/cnst.h | 3 + lib_com/common_api_types.h | 128 + lib_com/ivas_error.h | 16 + {lib_rend => lib_com}/ivas_limiter.c | 0 lib_com/ivas_prot.h | 1 + lib_com/ivas_prot_fx.h | 101 +- lib_com/ivas_rotation_com.c | 270 + lib_com/options.h | 6 + lib_dec/ivas_binRenderer_internal.c | 95 +- lib_dec/ivas_dirac_dec.c | 116 +- lib_dec/ivas_init_dec.c | 311 +- lib_dec/ivas_ism_dec.c | 31 +- lib_dec/ivas_ism_param_dec.c | 18 +- lib_dec/ivas_jbm_dec.c | 147 +- lib_dec/ivas_masa_dec.c | 48 + lib_dec/ivas_mc_param_dec.c | 52 + lib_dec/ivas_mc_paramupmix_dec.c | 61 + lib_dec/ivas_mct_dec.c | 40 +- lib_dec/ivas_objectRenderer_internal.c | 155 + lib_dec/ivas_omasa_dec.c | 74 +- lib_dec/ivas_osba_dec.c | 73 +- lib_dec/ivas_output_config.c | 42 +- lib_dec/ivas_sba_dec.c | 40 +- lib_dec/ivas_spar_decoder.c | 6 +- lib_dec/ivas_stat_dec.h | 46 +- lib_isar/isar_MSPred.c | 550 + lib_isar/isar_NoiseGen.c | 58 + lib_isar/isar_PerceptualModel.c | 469 + lib_isar/isar_PredDecoder.c | 496 + lib_isar/isar_PredEncoder.c | 1215 + lib_isar/isar_RMSEnvGrouping.c | 964 + lib_isar/isar_cnst.h | 159 + lib_isar/isar_lc3plus_common.c | 89 + lib_isar/isar_lc3plus_common.h | 72 + lib_isar/isar_lc3plus_dec.c | 857 + lib_isar/isar_lc3plus_dec.h | 136 + lib_isar/isar_lc3plus_enc.c | 697 + lib_isar/isar_lc3plus_enc.h | 104 + lib_isar/isar_lc3plus_payload.c | 823 + lib_isar/isar_lc3plus_payload.h | 216 + lib_isar/isar_lcld_decoder.c | 1993 ++ lib_isar/isar_lcld_encoder.c | 2143 ++ lib_isar/isar_lcld_prot.h | 457 + lib_isar/isar_lcld_rom_tables.c | 21207 ++++++++++++++++++ lib_isar/isar_lcld_rom_tables.h | 245 + lib_isar/isar_prot.h | 465 + lib_isar/isar_rom_post_rend.c | 196 + lib_isar/isar_rom_post_rend.h | 82 + lib_isar/isar_splitRend_lcld_dec.c | 284 + lib_isar/isar_splitRend_lcld_enc.c | 239 + lib_isar/isar_splitRendererPLC.c | 1316 ++ lib_isar/isar_splitRendererPost.c | 2131 ++ lib_isar/isar_splitRendererPre.c | 3469 +++ lib_isar/isar_splitRenderer_utils.c | 1741 ++ lib_isar/isar_stat.h | 267 + lib_isar/lib_isar_post_rend.c | 1913 ++ lib_isar/lib_isar_post_rend.h | 225 + lib_isar/lib_isar_pre_rend.c | 626 + lib_isar/lib_isar_pre_rend.h | 92 + lib_lc3plus/.clang-format | 2 + lib_lc3plus/adjust_global_gain_fx.c | 186 + lib_lc3plus/al_fec.c | 2379 ++ lib_lc3plus/apply_global_gain_fx.c | 66 + lib_lc3plus/ari_codec.c | 2465 ++ lib_lc3plus/attack_detector_fx.c | 119 + lib_lc3plus/basop_mpy_lc3plus.c | 99 + lib_lc3plus/basop_mpy_lc3plus.h | 94 + lib_lc3plus/basop_util_lc3plus.c | 1069 + lib_lc3plus/basop_util_lc3plus.h | 377 + lib_lc3plus/constants.c | 5046 +++++ lib_lc3plus/constants.h | 402 + lib_lc3plus/cutoff_bandwidth.c | 26 + lib_lc3plus/dct2_fx.c | 473 + lib_lc3plus/dct4_fx.c | 228 + lib_lc3plus/dec_entropy.c | 387 + lib_lc3plus/dec_lc3.c | 788 + lib_lc3plus/defines.h | 734 + lib_lc3plus/detect_cutoff_warped_fx.c | 124 + lib_lc3plus/dynmem.c | 288 + lib_lc3plus/dynmem.h | 80 + lib_lc3plus/enc_entropy.c | 173 + lib_lc3plus/enc_lc3.c | 680 + lib_lc3plus/estimate_global_gain_fx.c | 506 + lib_lc3plus/fft_lc3plus.c | 4537 ++++ lib_lc3plus/functions.h | 836 + lib_lc3plus/imdct_fx.c | 387 + lib_lc3plus/lc3.c | 426 + lib_lc3plus/lc3.h | 520 + lib_lc3plus/levinson_fx.c | 160 + lib_lc3plus/license.h | 21 + lib_lc3plus/ltpf_coder_fx.c | 323 + lib_lc3plus/ltpf_decoder_fx.c | 394 + lib_lc3plus/makefile | 180 + lib_lc3plus/mdct_fx.c | 223 + lib_lc3plus/mdct_shaping_fx.c | 74 + lib_lc3plus/near_nyquist_detector_fx.c | 141 + lib_lc3plus/noise_factor_fx.c | 252 + lib_lc3plus/noise_filling_fx.c | 149 + lib_lc3plus/olpa_fx.c | 289 + lib_lc3plus/pc_apply_fx.c | 315 + lib_lc3plus/pc_classify_fx.c | 260 + lib_lc3plus/pc_main_fx.c | 57 + lib_lc3plus/pc_update_fx.c | 148 + lib_lc3plus/per_band_energy_fx.c | 275 + lib_lc3plus/plc_apply_fx.c | 419 + lib_lc3plus/plc_classify_fx.c | 424 + lib_lc3plus/plc_damping_scrambling_fx.c | 430 + lib_lc3plus/plc_lpc_scaling_fx.c | 36 + lib_lc3plus/plc_main_fx.c | 85 + lib_lc3plus/plc_noise_substitution_fx.c | 32 + lib_lc3plus/plc_phecu_f0_refine_first_fx.c | 100 + lib_lc3plus/plc_phecu_fec_hq_fx.c | 3157 +++ lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c | 202 + lib_lc3plus/plc_phecu_peak_locator_fx.c | 385 + lib_lc3plus/plc_phecu_setf0hz_fx.c | 60 + lib_lc3plus/plc_phecu_tools_fx.c | 247 + lib_lc3plus/plc_tdac_fx.c | 217 + lib_lc3plus/plc_tdc_inverse_odft_fx.c | 130 + lib_lc3plus/plc_tdc_lagwin_fx.c | 32 + lib_lc3plus/plc_tdc_main_fx.c | 1257 ++ lib_lc3plus/plc_tdc_pre_emphasis_fx.c | 95 + lib_lc3plus/plc_update_aft_imdct_fx.c | 343 + lib_lc3plus/plc_update_fx.c | 224 + lib_lc3plus/plc_xcorr_fx.c | 250 + lib_lc3plus/pvq_dec_fx.c | 153 + lib_lc3plus/pvq_enc_fx.c | 369 + lib_lc3plus/pvq_index_fx.c | 513 + lib_lc3plus/quantize_spec_fx.c | 1167 + lib_lc3plus/reorder_bitstream_fx.c | 56 + lib_lc3plus/resamp12k8_fx.c | 121 + lib_lc3plus/residual_coding_fx.c | 238 + lib_lc3plus/residual_decoding_fx.c | 207 + lib_lc3plus/rom_basop_util.c | 2904 +++ lib_lc3plus/rom_basop_util.h | 172 + lib_lc3plus/scale_signal24_fx.c | 121 + lib_lc3plus/setup_dec_lc3.c | 539 + lib_lc3plus/setup_dec_lc3.h | 185 + lib_lc3plus/setup_enc_lc3.c | 760 + lib_lc3plus/setup_enc_lc3.h | 131 + lib_lc3plus/sns_compute_scf_fx.c | 166 + lib_lc3plus/sns_interpolate_scf_fx.c | 154 + lib_lc3plus/sns_quantize_scf_fx.c | 834 + lib_lc3plus/tinywavein_c.h | 603 + lib_lc3plus/tinywaveout_c.h | 889 + lib_lc3plus/tns_coder_fx.c | 378 + lib_lc3plus/tns_decoder_fx.c | 150 + lib_rend/ivas_prot_rend.h | 66 - lib_rend/ivas_rotation.c | 47 - lib_rend/ivas_stat_rend.h | 7 + lib_rend/lib_rend.h | 14 - 157 files changed, 96362 insertions(+), 218 deletions(-) create mode 100644 Workspace_msvc/isar_post_rend.vcxproj create mode 100644 Workspace_msvc/lib_isar.vcxproj create mode 100644 Workspace_msvc/lib_lc3plus.vcxproj create mode 100644 apps/isar_post_rend.c rename {lib_rend => lib_com}/ivas_limiter.c (100%) create mode 100644 lib_com/ivas_rotation_com.c create mode 100644 lib_isar/isar_MSPred.c create mode 100644 lib_isar/isar_NoiseGen.c create mode 100644 lib_isar/isar_PerceptualModel.c create mode 100644 lib_isar/isar_PredDecoder.c create mode 100644 lib_isar/isar_PredEncoder.c create mode 100644 lib_isar/isar_RMSEnvGrouping.c create mode 100644 lib_isar/isar_cnst.h create mode 100644 lib_isar/isar_lc3plus_common.c create mode 100644 lib_isar/isar_lc3plus_common.h create mode 100644 lib_isar/isar_lc3plus_dec.c create mode 100644 lib_isar/isar_lc3plus_dec.h create mode 100644 lib_isar/isar_lc3plus_enc.c create mode 100644 lib_isar/isar_lc3plus_enc.h create mode 100644 lib_isar/isar_lc3plus_payload.c create mode 100644 lib_isar/isar_lc3plus_payload.h create mode 100644 lib_isar/isar_lcld_decoder.c create mode 100644 lib_isar/isar_lcld_encoder.c create mode 100644 lib_isar/isar_lcld_prot.h create mode 100644 lib_isar/isar_lcld_rom_tables.c create mode 100644 lib_isar/isar_lcld_rom_tables.h create mode 100644 lib_isar/isar_prot.h create mode 100644 lib_isar/isar_rom_post_rend.c create mode 100644 lib_isar/isar_rom_post_rend.h create mode 100644 lib_isar/isar_splitRend_lcld_dec.c create mode 100644 lib_isar/isar_splitRend_lcld_enc.c create mode 100644 lib_isar/isar_splitRendererPLC.c create mode 100644 lib_isar/isar_splitRendererPost.c create mode 100644 lib_isar/isar_splitRendererPre.c create mode 100644 lib_isar/isar_splitRenderer_utils.c create mode 100644 lib_isar/isar_stat.h create mode 100644 lib_isar/lib_isar_post_rend.c create mode 100644 lib_isar/lib_isar_post_rend.h create mode 100644 lib_isar/lib_isar_pre_rend.c create mode 100644 lib_isar/lib_isar_pre_rend.h create mode 100644 lib_lc3plus/.clang-format create mode 100644 lib_lc3plus/adjust_global_gain_fx.c create mode 100644 lib_lc3plus/al_fec.c create mode 100644 lib_lc3plus/apply_global_gain_fx.c create mode 100644 lib_lc3plus/ari_codec.c create mode 100644 lib_lc3plus/attack_detector_fx.c create mode 100644 lib_lc3plus/basop_mpy_lc3plus.c create mode 100644 lib_lc3plus/basop_mpy_lc3plus.h create mode 100644 lib_lc3plus/basop_util_lc3plus.c create mode 100644 lib_lc3plus/basop_util_lc3plus.h create mode 100644 lib_lc3plus/constants.c create mode 100644 lib_lc3plus/constants.h create mode 100644 lib_lc3plus/cutoff_bandwidth.c create mode 100644 lib_lc3plus/dct2_fx.c create mode 100644 lib_lc3plus/dct4_fx.c create mode 100644 lib_lc3plus/dec_entropy.c create mode 100644 lib_lc3plus/dec_lc3.c create mode 100644 lib_lc3plus/defines.h create mode 100644 lib_lc3plus/detect_cutoff_warped_fx.c create mode 100644 lib_lc3plus/dynmem.c create mode 100644 lib_lc3plus/dynmem.h create mode 100644 lib_lc3plus/enc_entropy.c create mode 100644 lib_lc3plus/enc_lc3.c create mode 100644 lib_lc3plus/estimate_global_gain_fx.c create mode 100644 lib_lc3plus/fft_lc3plus.c create mode 100644 lib_lc3plus/functions.h create mode 100644 lib_lc3plus/imdct_fx.c create mode 100644 lib_lc3plus/lc3.c create mode 100644 lib_lc3plus/lc3.h create mode 100644 lib_lc3plus/levinson_fx.c create mode 100644 lib_lc3plus/license.h create mode 100644 lib_lc3plus/ltpf_coder_fx.c create mode 100644 lib_lc3plus/ltpf_decoder_fx.c create mode 100644 lib_lc3plus/makefile create mode 100644 lib_lc3plus/mdct_fx.c create mode 100644 lib_lc3plus/mdct_shaping_fx.c create mode 100644 lib_lc3plus/near_nyquist_detector_fx.c create mode 100644 lib_lc3plus/noise_factor_fx.c create mode 100644 lib_lc3plus/noise_filling_fx.c create mode 100644 lib_lc3plus/olpa_fx.c create mode 100644 lib_lc3plus/pc_apply_fx.c create mode 100644 lib_lc3plus/pc_classify_fx.c create mode 100644 lib_lc3plus/pc_main_fx.c create mode 100644 lib_lc3plus/pc_update_fx.c create mode 100644 lib_lc3plus/per_band_energy_fx.c create mode 100644 lib_lc3plus/plc_apply_fx.c create mode 100644 lib_lc3plus/plc_classify_fx.c create mode 100644 lib_lc3plus/plc_damping_scrambling_fx.c create mode 100644 lib_lc3plus/plc_lpc_scaling_fx.c create mode 100644 lib_lc3plus/plc_main_fx.c create mode 100644 lib_lc3plus/plc_noise_substitution_fx.c create mode 100644 lib_lc3plus/plc_phecu_f0_refine_first_fx.c create mode 100644 lib_lc3plus/plc_phecu_fec_hq_fx.c create mode 100644 lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c create mode 100644 lib_lc3plus/plc_phecu_peak_locator_fx.c create mode 100644 lib_lc3plus/plc_phecu_setf0hz_fx.c create mode 100644 lib_lc3plus/plc_phecu_tools_fx.c create mode 100644 lib_lc3plus/plc_tdac_fx.c create mode 100644 lib_lc3plus/plc_tdc_inverse_odft_fx.c create mode 100644 lib_lc3plus/plc_tdc_lagwin_fx.c create mode 100644 lib_lc3plus/plc_tdc_main_fx.c create mode 100644 lib_lc3plus/plc_tdc_pre_emphasis_fx.c create mode 100644 lib_lc3plus/plc_update_aft_imdct_fx.c create mode 100644 lib_lc3plus/plc_update_fx.c create mode 100644 lib_lc3plus/plc_xcorr_fx.c create mode 100644 lib_lc3plus/pvq_dec_fx.c create mode 100644 lib_lc3plus/pvq_enc_fx.c create mode 100644 lib_lc3plus/pvq_index_fx.c create mode 100644 lib_lc3plus/quantize_spec_fx.c create mode 100644 lib_lc3plus/reorder_bitstream_fx.c create mode 100644 lib_lc3plus/resamp12k8_fx.c create mode 100644 lib_lc3plus/residual_coding_fx.c create mode 100644 lib_lc3plus/residual_decoding_fx.c create mode 100644 lib_lc3plus/rom_basop_util.c create mode 100644 lib_lc3plus/rom_basop_util.h create mode 100644 lib_lc3plus/scale_signal24_fx.c create mode 100644 lib_lc3plus/setup_dec_lc3.c create mode 100644 lib_lc3plus/setup_dec_lc3.h create mode 100644 lib_lc3plus/setup_enc_lc3.c create mode 100644 lib_lc3plus/setup_enc_lc3.h create mode 100644 lib_lc3plus/sns_compute_scf_fx.c create mode 100644 lib_lc3plus/sns_interpolate_scf_fx.c create mode 100644 lib_lc3plus/sns_quantize_scf_fx.c create mode 100644 lib_lc3plus/tinywavein_c.h create mode 100644 lib_lc3plus/tinywaveout_c.h create mode 100644 lib_lc3plus/tns_coder_fx.c create mode 100644 lib_lc3plus/tns_decoder_fx.c diff --git a/Workspace_msvc/isar_post_rend.vcxproj b/Workspace_msvc/isar_post_rend.vcxproj new file mode 100644 index 000000000..19cb1aff7 --- /dev/null +++ b/Workspace_msvc/isar_post_rend.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + isar_post_rend + {12374ADC-0E5C-4FDD-B903-71D572413831} + isar_post_rend + 10.0.17763.0 + + + + Application + v141 + false + MultiByte + + + Application + v141 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27428.2015 + + + ..\ + .\Debug_$(ProjectName)\ + false + false + ISAR_post_rend + + + ..\ + .\Release_$(ProjectName)\ + false + false + ISAR_post_rend + + + + $(IntDir)$(ProjectName).tlb + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_util;..\lib_isar;..\lib_lc3plus;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + OldStyle + Default + %(DisableSpecificWarnings) + false + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + $(OutDir)$(TargetName).exe + true + + true + $(IntDir)$(ProjectName).pdb + Console + false + + MachineX86 + + + + + $(IntDir)$(ProjectName).tlb + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_com;..\lib_debug;..\lib_util;..\lib_isar;..\lib_lc3plus;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + Precise + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + + Default + %(DisableSpecificWarnings) + false + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + $(OutDir)$(TargetName).exe + true + + false + $(IntDir)$(ProjectName).pdb + Console + false + + MachineX86 + libcmtd.lib + + + + + + + + + + {54509728-928B-44D9-A118-A6F92F08B34F} + false + + + {869a305e-d99e-4c3a-bdb3-aa57abcce619} + + + {2FA8F384-0775-F3B7-F8C3-85209222FC70} + false + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + + + + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/lib_isar.vcxproj b/Workspace_msvc/lib_isar.vcxproj new file mode 100644 index 000000000..c663ef5e7 --- /dev/null +++ b/Workspace_msvc/lib_isar.vcxproj @@ -0,0 +1,202 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + lib_isar + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619} + evs_dec + 10.0.17763.0 + + + StaticLibrary + v141 + false + MultiByte + + + + StaticLibrary + v141 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27428.2015 + + + .\Debug_$(ProjectName)\ + .\Debug_$(ProjectName)\ + false + false + libivasrend + + + .\Release_$(ProjectName)\ + .\Release_$(ProjectName)\ + false + false + libivasrend + + + + + + + .\Debug\$(ProjectName).tlb + + + + Disabled + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_lc3plus;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + OldStyle + Default + %(DisableSpecificWarnings) + false + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib; %(AdditionalDependencies) + $(OutDir)$(TargetName).lib + true + + + + + + + + $(IntDir)$(ProjectName).tlb + + + + MaxSpeed + AnySuitable + false + Neither + false + false + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_lc3plus;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + false + + + $(IntDir)$(ProjectName).pdb + Level4 + true + + Default + %(DisableSpecificWarnings) + false + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib; %(AdditionalDependencies) + $(OutDir)$(TargetName).lib + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + {54509728-928b-44d9-a118-a6f92f08b34f} + false + + + {95030B82-70CD-4C6B-84D4-61096035BEA2} + false + + + + + + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj new file mode 100644 index 000000000..294677fff --- /dev/null +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -0,0 +1,195 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {95030B82-70CD-4C6B-84D4-61096035BEA2} + Win32Proj + LC3_FL + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + liblc3plus + .\Debug_$(ProjectName)\ + .\Debug_$(ProjectName)\ + + + LC3plus + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\Obj\ + + + + + + Level3 + ..\lib_com;%(AdditionalIncludeDirectories) + Disabled + MultiThreadedDebug + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + 4305;4244;4996 + OldStyle + false + false + + + Console + true + + + + + Level3 + + + ..\lib_com;%(AdditionalIncludeDirectories) + MaxSpeed + MultiThreaded + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + 4244;4305;4996 + false + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/decoder.c b/apps/decoder.c index 058722569..65c949ace 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -43,6 +43,9 @@ #include "masa_file_writer.h" #include "render_config_reader.h" #include "rotation_file_reader.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "split_render_file_read_write.h" +#endif #include "vector3_pair_file_reader.h" #include "wmc_auto.h" #include "options.h" @@ -114,6 +117,9 @@ typedef struct Word16 non_diegetic_pan_gain_fx; /* Q15 */ bool renderConfigEnabled; char *renderConfigFilename; +#ifdef SPLIT_REND_WITH_HEAD_ROT + char *outputMdFilename; +#endif IVAS_DEC_COMPLEXITY_LEVEL complexityLevel; bool tsmEnabled; IVAS_RENDER_FRAMESIZE renderFramesize; @@ -130,7 +136,11 @@ typedef struct static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg ); static void usage_dec( void ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +#else static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); +#endif static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, IVAS_DEC_HANDLE hIvasDec ); @@ -147,6 +157,10 @@ int main( bool mainFailed = true; /* Assume main failed until cleanup is reached without errors */ DecArguments arg; ivas_error error = IVAS_ERR_UNKNOWN; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_BITS_DATA splitRendBits; + uint8_t splitRendBitsBuf[ISAR_MAX_SPLIT_REND_BITS_BUFFER_SIZE_IN_BYTES]; +#endif /* Any handles that require cleanup must be declared here and initialized to NULL */ IVAS_DEC_HANDLE hIvasDec = NULL; @@ -166,6 +180,10 @@ int main( reset_mem( USE_BYTES ); #endif +#ifdef SPLIT_REND_WITH_HEAD_ROT + splitRendBits.bits_buf = splitRendBitsBuf; +#endif + /*------------------------------------------------------------------------------------------* * Parse command-line arguments *------------------------------------------------------------------------------------------*/ @@ -212,6 +230,18 @@ int main( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + fprintf( stdout, "Output metadata file: %s\n", arg.outputWavFilename ); + } + else if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + fprintf( stdout, "Output synthesis file: %s\n", arg.outputWavFilename ); + fprintf( stdout, "Output metadata file: %s\n", arg.outputMdFilename ); + } + else +#endif { fprintf( stdout, "Output synthesis file: %s\n", arg.outputWavFilename ); } @@ -245,7 +275,11 @@ int main( if ( arg.enableHeadRotation ) { /* sanity check */ - if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB +#ifdef SPLIT_REND_WITH_HEAD_ROT + && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM +#endif + ) { fprintf( stderr, "\nError: Head-rotation file file cannot be used in this output configuration.\n\n" ); goto cleanup; @@ -345,7 +379,12 @@ int main( if ( arg.renderConfigEnabled ) { /* sanity check */ - if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB +#ifdef SPLIT_REND_WITH_HEAD_ROT + && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && + arg.Opt_non_diegetic_pan == 0 +#endif + ) { fprintf( stderr, "\nError: Renderer configuration file cannot be used in this output configuration.\n\n" ); goto cleanup; @@ -381,10 +420,29 @@ int main( fprintf( stderr, "\nChanged render framesize, only 20ms are allowed for decoding to EXT!\n" ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT /*------------------------------------------------------------------------------------------* * Configure Split rendering *------------------------------------------------------------------------------------------*/ + asked_frame_size = arg.renderFramesize; + if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( ( error = IVAS_DEC_EnableSplitRendering( hIvasDec ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + if ( ( error = IVAS_DEC_GetRenderFramesize( hIvasDec, &arg.renderFramesize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + arg.enableHeadRotation = true; + } +#endif /*------------------------------------------------------------------------------------------* * Configure VoIP mode @@ -410,11 +468,21 @@ int main( IVAS_RENDER_CONFIG_DATA renderConfig; /* sanity check */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB && + arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && + arg.Opt_non_diegetic_pan == 0 ) + { + fprintf( stderr, "\nExternal Renderer Config is supported only when binaural output configurations is used as output OR when Split rendering mode is enabled. Exiting. \n" ); + goto cleanup; + } +#else if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { fprintf( stderr, "\nExternal Renderer Config is supported only for binaural output configurations. Exiting. \n\n" ); goto cleanup; } +#endif if ( ( error = IVAS_DEC_GetRenderConfig( hIvasDec, &renderConfig ) ) != IVAS_ERR_OK ) { @@ -422,7 +490,6 @@ int main( goto cleanup; } - if ( RenderConfigReader_read( renderConfigReader, arg.renderConfigFilename, &renderConfig ) != IVAS_ERR_OK ) { fprintf( stderr, "Failed to read renderer configuration from file %s\n\n", arg.renderConfigFilename ); @@ -441,6 +508,33 @@ int main( renderConfig.directivity_fx[i * 3 + 2] = (Word16) ( renderConfig.directivity[i * 3 + 2] * ( ( 1u << 15 ) - 1 ) ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || + arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + if ( asked_frame_size != IVAS_RENDER_FRAMESIZE_20MS && + ( renderConfig.split_rend_config.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE || + renderConfig.split_rend_config.dof == 0 ) ) + { + arg.renderFramesize = asked_frame_size; + } + else + { + arg.renderFramesize = IVAS_RENDER_FRAMESIZE_20MS; + } + + if ( ( error = IVAS_DEC_SetRenderFramesize( hIvasDec, arg.renderFramesize ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( arg.renderFramesize != asked_frame_size ) + { + fprintf( stderr, "\nChanged render framesize, only 20ms are allowed for non-0dof split rendering!\n" ); + } + } +#endif + if ( arg.outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, arg.acousticEnvironmentId, &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) @@ -458,6 +552,13 @@ int main( } renderConfig.roomAcoustics.override = true; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* ISAR frame size is set from command line, not renderer config file. + * This will be ignored if output format is not split rendering. */ + renderConfig.split_rend_config.isar_frame_size_ms = (int16_t) arg.renderFramesize /* given in number of 5ms subframes */ * 5; +#endif +#endif if ( ( error = IVAS_DEC_FeedRenderConfig( hIvasDec, renderConfig ) ) != IVAS_ERR_OK ) { @@ -568,13 +669,18 @@ int main( /*-----------------------------------------------------------------* * Decoding *-----------------------------------------------------------------*/ + if ( arg.voipMode ) { error = decodeVoIP( arg, hBsReader, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, hIvasDec ); } else { +#ifdef SPLIT_REND_WITH_HEAD_ROT + error = decodeG192( arg, hBsReader, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, &splitRendBits, hIvasDec, pcmBuf ); +#else error = decodeG192( arg, hBsReader, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, hIvasDec, pcmBuf ); +#endif } if ( error == IVAS_ERR_OK || error == IVAS_ERR_END_OF_FILE ) @@ -708,6 +814,16 @@ static IVAS_AUDIO_CONFIG cmdline2config( { output_config = IVAS_AUDIO_CONFIG_BINAURAL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + else if ( strcmp( argv_to_upper, "BINAURAL_SPLIT_CODED" ) == 0 ) + { + output_config = IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED; + } + else if ( strcmp( argv_to_upper, "BINAURAL_SPLIT_PCM" ) == 0 ) + { + output_config = IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM; + } +#endif else if ( strcmp( argv_to_upper, "BINAURAL_ROOM_IR" ) == 0 ) { output_config = IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR; @@ -775,6 +891,9 @@ static bool parseCmdlIVAS_dec( arg->renderConfigFilename = NULL; arg->Opt_dpid_on = 0; +#ifdef SPLIT_REND_WITH_HEAD_ROT + arg->outputMdFilename = NULL; +#endif arg->inputFormat = IVAS_DEC_INPUT_FORMAT_G192; arg->Opt_non_diegetic_pan = 0; @@ -1022,6 +1141,19 @@ static bool parseCmdlIVAS_dec( } i += 2; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + else if ( strcmp( argv_to_upper, "-OM" ) == 0 ) + { + arg->outputMdFilename = argv[i + 1]; + if ( arg->outputMdFilename[0] == '\0' ) + { + fprintf( stderr, "Error: output metadata file path not specified\n\n" ); + usage_dec(); + return false; + } + i += 2; + } +#endif else if ( strcmp( argv_to_upper, "-NON_DIEGETIC_PAN" ) == 0 ) { i++; @@ -1172,6 +1304,14 @@ static bool parseCmdlIVAS_dec( usage_dec(); return false; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( arg->outputMdFilename != NULL && arg->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + fprintf( stderr, "Error: Output split rendering metadata file is supported for BINAURAL_SPLIT_PCM output config. only\n\n" ); + usage_dec(); + return false; + } +#endif } else { @@ -1248,8 +1388,13 @@ static void usage_dec( void ) fprintf( stdout, "Mandatory parameters:\n" ); fprintf( stdout, "---------------------\n" ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + fprintf( stdout, "OutputConf : Output configuration: MONO, STEREO, 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4, FOA,\n" ); + fprintf( stdout, " HOA2, HOA3, BINAURAL, BINAURAL_ROOM_IR, BINAURAL_ROOM_REVERB, BINAURAL_SPLIT_CODED, BINAURAL_SPLIT_PCM, EXT\n" ); +#else fprintf( stdout, "OutputConf : Output configuration: MONO, STEREO, 5_1, 7_1, 5_1_2, 5_1_4, 7_1_4, FOA,\n" ); fprintf( stdout, " HOA2, HOA3, BINAURAL, BINAURAL_ROOM_IR, BINAURAL_ROOM_REVERB, EXT\n" ); +#endif fprintf( stdout, " By default, channel order and loudspeaker positions are equal to the\n" ); fprintf( stdout, " encoder. For loudspeaker outputs, OutputConf can be a custom loudspeaker\n" ); fprintf( stdout, " layout file. See readme.txt for details.\n" ); @@ -1289,6 +1434,9 @@ static void usage_dec( void ) fprintf( stdout, "-rvf File : Reference vector specified by external trajectory File\n" ); fprintf( stdout, " works only in combination with '-otr ref_vec' and 'ref_vec_lev' modes\n" ); fprintf( stdout, "-render_config File : Renderer configuration File\n" ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + fprintf( stdout, "-om File : Metadata output File for BINAURAL_SPLIT_PCM OutputConf (only for Fs = 48 kHz)\n" ); +#endif fprintf( stdout, "-non_diegetic_pan P : panning mono non-diegetic sound to stereo with paning P, -90<= P <=90,\n" ); fprintf( stdout, " left or l or 90->left, right or r or -90->right, center or c or 0->middle\n" ); fprintf( stdout, "-exof File : External orientation File for external orientation trajectory\n" ); @@ -1318,7 +1466,12 @@ static ivas_error initOnFirstGoodFrame( IVAS_DEC_HANDLE hIvasDec, /* i/o: */ const DecArguments arg, /* i : */ const int16_t numInitialBadFrames, /* i : */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t *numOutSamples, /* i/o: */ + int16_t *vec_pos_len, /* i/o: */ +#else const uint16_t numOutSamples, /* i : */ +#endif int16_t *pFullDelayNumSamples, /* o : */ int16_t *pRemainingDelayNumSamples, /* o : */ int32_t *delayTimeScale, /* o : */ @@ -1327,7 +1480,12 @@ static ivas_error initOnFirstGoodFrame( MasaFileWriter **ppMasaWriter, /* o : */ IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS], /* o : */ int16_t *pNumOutChannels, /* o : */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + uint16_t *pNumObj, /* o : */ + SplitFileReadWrite **splitRendWriter +#else uint16_t *pNumObj /* o : */ +#endif ) { ivas_error error = IVAS_ERR_UNKNOWN; @@ -1339,6 +1497,12 @@ static ivas_error initOnFirstGoodFrame( return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( IVAS_DEC_is_split_rendering_enabled( hIvasDec ) ) + { + pFullDelayNumSamples[0] = 0; + } +#endif if ( !arg.delayCompensationEnabled ) { @@ -1360,22 +1524,149 @@ static ivas_error initOnFirstGoodFrame( return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( IVAS_DEC_is_split_rendering_enabled( hIvasDec ) ) + { + /* Open split rendering metadata writer */ + int16_t delayNumSamples_temp[3]; + int32_t delayTimeScale_temp; + ISAR_SPLIT_REND_CODEC splitRendCodec; + int16_t splitRendCodecFrameSizeMs; + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t splitRendIsarFrameSizeMs; + int16_t lc3plusHighRes; +#endif + + if ( ( error = IVAS_DEC_GetDelay( hIvasDec, delayNumSamples_temp, &delayTimeScale_temp ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get delay of decoder: %s\n", ivas_error_to_string( error ) ); + return error; + } + + if ( ( error = IVAS_DEC_GetSplitRendBitstreamHeader( hIvasDec, + &splitRendCodec, + &poseCorrection, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + &splitRendIsarFrameSizeMs, +#endif + &splitRendCodecFrameSizeMs +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + &lc3plusHighRes +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get split renderer bitstream header: %s\n", ivas_error_to_string( error ) ); + return error; + } + + if ( IVAS_DEC_is_split_rendering_coded_out( hIvasDec ) ) + { + if ( ( error = split_rend_writer_open( splitRendWriter, + arg.outputWavFilename, + delayNumSamples_temp[0], + delayTimeScale_temp, + splitRendCodec, + poseCorrection, + splitRendCodecFrameSizeMs +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + splitRendIsarFrameSizeMs, + arg.output_Fs, + lc3plusHighRes +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to open output split rendering metadata file %s\n", arg.outputWavFilename ); + return error; + } + } + else + { + if ( arg.outputMdFilename == NULL ) + { + fprintf( stderr, "\nOutput split rendering metadata file not specified\n" ); + return IVAS_ERR_INVALID_SPLIT_REND_CONFIG; + } + + if ( ( error = split_rend_writer_open( splitRendWriter, + arg.outputMdFilename, + delayNumSamples_temp[0], + delayTimeScale_temp, + splitRendCodec, + poseCorrection, + splitRendCodecFrameSizeMs +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + splitRendIsarFrameSizeMs, + arg.output_Fs, + lc3plusHighRes +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to open output split rendering metadata file %s\n", arg.outputWavFilename ); + return error; + } + } + } + + if ( IVAS_DEC_is_split_rendering_coded_out( hIvasDec ) == 0 ) + { +#endif /* Open audio writer and write all previously skipped bad frames now that frame size is known */ if ( ( error = AudioFileWriter_open( ppAfWriter, arg.outputWavFilename, arg.output_Fs, *pNumOutChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif int16_t *zeroBuf = malloc( pcmFrameSize * sizeof( int16_t ) ); memset( zeroBuf, 0, pcmFrameSize * sizeof( int16_t ) ); for ( int16_t i = 0; i < numInitialBadFrames; ++i ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( *splitRendWriter != NULL ) + { + ISAR_SPLIT_REND_BITS_DATA splitRendBitsZero; + splitRendBitsZero.bits_buf = NULL; + splitRendBitsZero.bits_read = 0; + splitRendBitsZero.bits_written = 0; + splitRendBitsZero.buf_len = 0; + splitRendBitsZero.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + splitRendBitsZero.pose_correction = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + splitRendBitsZero.codec_frame_size_ms = 0; + splitRendBitsZero.isar_frame_size_ms = 20; +#else + splitRendBitsZero.codec_frame_size_ms = 20; +#endif + if ( split_rend_write_bitstream_to_file( *splitRendWriter, splitRendBitsZero.bits_buf, &splitRendBitsZero.bits_read, &splitRendBitsZero.bits_written ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to write to bitstream file!\n" ); + return error; + } + } + else + { +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( *pRemainingDelayNumSamples < *numOutSamples ) +#else if ( *pRemainingDelayNumSamples < numOutSamples ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, *numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) +#else if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nOutput audio file writer error\n" ); return error; @@ -1384,8 +1675,15 @@ static ivas_error initOnFirstGoodFrame( } else { +#ifdef SPLIT_REND_WITH_HEAD_ROT + *pRemainingDelayNumSamples -= *numOutSamples; +#else *pRemainingDelayNumSamples -= numOutSamples; +#endif + } +#ifdef SPLIT_REND_WITH_HEAD_ROT } +#endif } free( zeroBuf ); @@ -1452,6 +1750,7 @@ static ivas_error initOnFirstGoodFrame( { /* Duplicate good first frame metadata to fill the beginning of stream. */ IVAS_MASA_DECODER_EXT_OUT_META_HANDLE hMasaExtOutMeta = NULL; + if ( ( error = IVAS_DEC_GetMasaMetadata( hIvasDec, &hMasaExtOutMeta, 0 ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_GetMasaMetadata: %s\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -1470,6 +1769,27 @@ static ivas_error initOnFirstGoodFrame( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( *splitRendWriter != NULL ) + { + if ( numOutSamples == NULL || vec_pos_len == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + /* real setting of the 5ms mode for split rendering is only known after the decoded first good frame, reset the variables needed in the main decoding loop accordingly here*/ + if ( ( error = IVAS_DEC_GetRenderFramesizeSamples( hIvasDec, numOutSamples ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError getting render frame size in samples\n" ); + return error; + } + if ( ( error = IVAS_DEC_GetReferencesUpdateFrequency( hIvasDec, vec_pos_len ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError getting render frame size in samples\n" ); + return error; + } + } +#endif return IVAS_ERR_OK; } @@ -1488,6 +1808,9 @@ static ivas_error decodeG192( RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, +#endif IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ) @@ -1514,7 +1837,9 @@ static ivas_error decodeG192( IsmFileWriter *ismWriters[IVAS_MAX_NUM_OBJECTS]; IVAS_VECTOR3 Pos[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES] = { { 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 } }; int16_t vec_pos_update, vec_pos_len; - +#ifdef SPLIT_REND_WITH_HEAD_ROT + SplitFileReadWrite *splitRendWriter = NULL; +#endif for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; ++i ) { @@ -1612,18 +1937,42 @@ static ivas_error decodeG192( { IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; - for ( i = 0; i < num_subframes; i++ ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( headRotReader == NULL ) { - if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + for ( i = 0; i < num_subframes; i++ ) { - fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), RotationFileReader_getFilePath( headRotReader ) ); - goto cleanup; + Quaternions[i].w = -3.0f; + Quaternions[i].x = 0.0f; + Quaternions[i].y = 0.0f; + Quaternions[i].z = 0.0f; + Pos[i].x = 0.0f; + Pos[i].y = 0.0f; + Pos[i].z = 0.0f; } } + else + { +#endif + for ( i = 0; i < num_subframes; i++ ) + { + if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), RotationFileReader_getFilePath( headRotReader ) ); + goto cleanup; + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif for ( i = 0; i < num_subframes; i++ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions[i], Pos[i], i, DEFAULT_AXIS ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions[i], Pos[i], i ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -1681,14 +2030,38 @@ static ivas_error decodeG192( goto cleanup; } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( IVAS_DEC_is_split_rendering_enabled( hIvasDec ) ) + { + if ( ( error = IVAS_DEC_GetSplitBinauralBitstream( hIvasDec, (void *) ( pcmBuf + nOutChannels * nSamplesRendered ), splitRendBits, &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetSplitBinauralBitstream: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + + nSamplesRendered += nSamplesRendered_loop; + nSamplesToRender -= nSamplesRendered_loop; + } + else + { +#endif +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, IVAS_DEC_PCM_INT16, (void *) ( pcmBuf + nOutChannels * nSamplesRendered ), &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) + +#else if ( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, ( pcmBuf + nOutChannels * nSamplesRendered ), &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError in IVAS_DEC_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } nSamplesRendered += nSamplesRendered_loop; nSamplesToRender -= nSamplesRendered_loop; +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif if ( needNewFrame ) { @@ -1719,7 +2092,11 @@ static ivas_error decodeG192( /* Once good frame decoded, catch up */ if ( decodedGoodFrame ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, &vec_pos_len, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &splitRendWriter ) ) != IVAS_ERR_OK ) +#else if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, nOutSamples, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj ) ) != IVAS_ERR_OK ) +#endif { goto cleanup; } @@ -1733,6 +2110,19 @@ static ivas_error decodeG192( /* Write current frame */ if ( decodedGoodFrame ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( IVAS_DEC_is_split_rendering_enabled( hIvasDec ) ) + { + if ( split_rend_write_bitstream_to_file( splitRendWriter, splitRendBits->bits_buf, &splitRendBits->bits_read, &splitRendBits->bits_written ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to write to bitstream file!\n" ); + goto cleanup; + } + } + + if ( IVAS_DEC_is_split_rendering_coded_out( hIvasDec ) == 0 ) + { +#endif if ( delayNumSamples < nOutSamples ) { if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) @@ -1746,6 +2136,9 @@ static ivas_error decodeG192( { delayNumSamples -= nOutSamples; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif } /* Write ISm metadata to external file(s) */ @@ -1859,7 +2252,11 @@ static ivas_error decodeG192( goto cleanup; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternion, Pos[0], 0, DEFAULT_AXIS ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternion, Pos[0], 0 ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -1867,7 +2264,11 @@ static ivas_error decodeG192( } /* decode and get samples */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -1979,11 +2380,18 @@ static ivas_error decodeG192( *------------------------------------------------------------------------------------------*/ memset( pcmBuf, 0, delayNumSamples_orig[0] * nOutChannels * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig[0] * nOutChannels ) ) != IVAS_ERR_OK ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( afWriter != NULL ) { - fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); - goto cleanup; +#endif + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, delayNumSamples_orig[0] * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError writing output file: %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } +#ifdef SPLIT_REND_WITH_HEAD_ROT } +#endif /*------------------------------------------------------------------------------------------* * Close files and deallocate resources @@ -1993,6 +2401,9 @@ static ivas_error decodeG192( cleanup: +#ifdef SPLIT_REND_WITH_HEAD_ROT + split_rend_reader_writer_close( &splitRendWriter ); +#endif AudioFileWriter_close( &afWriter ); MasaFileWriter_close( &masaWriter ); for ( i = 0; i < IVAS_MAX_NUM_OBJECTS; i++ ) @@ -2239,19 +2650,44 @@ static ivas_error decodeVoIP( { IVAS_QUATERNION Quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; - for ( i = 0; i < num_subframes; i++ ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( headRotReader == NULL ) { - if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + for ( i = 0; i < num_subframes; i++ ) { - fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), - RotationFileReader_getFilePath( headRotReader ) ); - goto cleanup; + Quaternions[i].w = -3.0f; + Quaternions[i].x = 0.0f; + Quaternions[i].y = 0.0f; + Quaternions[i].z = 0.0f; + Pos[i].x = 0.0f; + Pos[i].y = 0.0f; + Pos[i].z = 0.0f; } } + else + { +#endif + for ( i = 0; i < num_subframes; i++ ) + { + if ( ( error = HeadRotationFileReading( headRotReader, &Quaternions[i], &Pos[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError %s while reading head orientation from %s\n", IVAS_DEC_GetErrorMessage( error ), + RotationFileReader_getFilePath( headRotReader ) ); + goto cleanup; + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif for ( i = 0; i < num_subframes; i++ ) { - if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions[i], Pos[i], i ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_FeedHeadTrackData( hIvasDec, Quaternions[i], Pos[i], i +#ifdef SPLIT_REND_WITH_HEAD_ROT + , + DEFAULT_AXIS +#endif + ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_DEC_FeedHeadTrackData failed: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -2339,10 +2775,18 @@ static ivas_error decodeVoIP( /* decode and get samples */ +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef SUPPORT_JBM_TRACEFILE + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, systemTime_ms, writeJbmTraceFileFrameWrapper, jbmTraceWriter ) ) != IVAS_ERR_OK ) +#else + if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) +#endif +#else #ifdef SUPPORT_JBM_TRACEFILE if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms, writeJbmTraceFileFrameWrapper, jbmTraceWriter ) ) != IVAS_ERR_OK ) #else if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) +#endif #endif { fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -2379,8 +2823,15 @@ static ivas_error decodeVoIP( /* Once good frame decoded, catch up */ if ( decodedGoodFrame ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + SplitFileReadWrite *splitRendWriter = NULL; + + if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, NULL, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, + &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &splitRendWriter ) ) != IVAS_ERR_OK ) +#else if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, nOutSamples, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj ) ) != IVAS_ERR_OK ) +#endif { goto cleanup; } diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c new file mode 100644 index 000000000..9a8d7c3ba --- /dev/null +++ b/apps/isar_post_rend.c @@ -0,0 +1,1262 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include "lib_isar_post_rend.h" +//#undef IVAS_FLOAT_FIXED + +#ifndef SPLIT_REND_WITH_HEAD_ROT + +int main( int argc, char **argv ) +{ + (void) argc; + (void) argv; + ISAR_POST_REND_void_func(); + return 0; +} + +#else + +#include +#include +#include +#include "audio_file_reader.h" +#include "audio_file_writer.h" +#include "cmdl_tools.h" +#include "cmdln_parser.h" +#include "render_config_reader.h" +#include "rotation_file_reader.h" +#include "split_render_file_read_write.h" +#include "split_rend_bfi_file_reader.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "stl.h" +#include "wmc_auto.h" + + +#define WMC_TOOL_SKIP + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +#define POST_REND_MAX_CLI_ARG_LENGTH ( FILENAME_MAX ) + +#define ISAR_MAX16B_FLT 32767.0f +#define ISAR_MIN16B_FLT ( -32768.0f ) +#define ISAR_MAX16B_FX 32767 +#define ISAR_MIN16B_FX ( -32768 ) + +#if !defined( DEBUGGING ) && !defined( WMOPS ) +static +#endif + int32_t frame = 0; + +#ifdef _WIN32 +#define SEP_FOLDER '\\' +#else +#define SEP_FOLDER '/' +#endif + +/*------------------------------------------------------------------------------------------* + * Local structures + *------------------------------------------------------------------------------------------*/ + +typedef struct +{ + IVAS_AUDIO_CONFIG audioConfig; + int32_t inputChannelIndex; + float gain_dB; +} RendererInput; + +typedef struct +{ + RendererInput binBuses[RENDERER_MAX_BIN_INPUTS]; + uint16_t numBinBuses; +} InputConfig; + +typedef struct +{ + IVAS_AUDIO_CONFIG audioConfig; +} OutputConfig; + +typedef struct +{ + char executableName[POST_REND_MAX_CLI_ARG_LENGTH]; + char inputFilePath[POST_REND_MAX_CLI_ARG_LENGTH]; + char outputFilePath[POST_REND_MAX_CLI_ARG_LENGTH]; + int32_t sampleRate; + InputConfig inConfig; + OutputConfig outConfig; + char inMetadataFilePaths[RENDERER_MAX_ISAR_MD_INPUTS][POST_REND_MAX_CLI_ARG_LENGTH]; + int16_t numInMetadataFiles; + char headRotationFilePath[POST_REND_MAX_CLI_ARG_LENGTH]; + char splitRendBFIFilePath[POST_REND_MAX_CLI_ARG_LENGTH]; + ISAR_POST_REND_COMPLEXITY_LEVEL complexityLevel; + bool delayCompensationEnabled; + bool quietModeEnabled; + bool sceneDescriptionInput; + IVAS_RENDER_FRAMESIZE render_framesize; +} CmdlnArgs; + +typedef enum +{ + CmdLnOptionId_inputFile = 1, + CmdLnOptionId_inputFormat, + CmdLnOptionId_outputFile, + CmdLnOptionId_sampleRate, + CmdLnOptionId_trajFile, + CmdLnOptionId_orientationTracking, + CmdLnOptionId_complexityLevel, + CmdLnOptionId_noDelayCmp, + CmdLnOptionId_quietModeEnabled, + CmdLnOptionId_inputMetadata, + CmdLnOptionId_listFormats, + CmdLnOptionId_SplitRendBFIFile, + CmdLnOptionId_framing, +} CmdLnOptionId; + +static const CmdLnParser_Option cliOptions[] = { + { + .id = CmdLnOptionId_inputFile, + .match = "input_file", + .matchShort = "i", + .description = "Path to the input file (WAV, raw PCM or scene description file)", + }, + { + .id = CmdLnOptionId_inputFormat, + .match = "input_format", + .matchShort = "if", + .description = "Audio format of input file (e.g. BINAURAL_SPLIT_PCM, use -l for a list)", + }, + { + .id = CmdLnOptionId_inputMetadata, + .match = "input_metadata", + .matchShort = "im", + .description = "Space-separated list of path to metadata files for BINAURAL_SPLIT_PCM input mode", + }, + { + .id = CmdLnOptionId_outputFile, + .match = "output_file", + .matchShort = "o", + .description = "Path to the output file", + }, + { + .id = CmdLnOptionId_sampleRate, + .match = "sample_rate", + .matchShort = "fs", + .description = "Input sampling rate in kHz (16, 32, 48) - required only with raw PCM inputs", + }, + { + .id = CmdLnOptionId_trajFile, + .match = "trajectory_file", + .matchShort = "T", + .description = "Head rotation trajectory file for simulation of head tracking", + }, + { + .id = CmdLnOptionId_SplitRendBFIFile, + .match = "post_rend_bfi_file", + .matchShort = "prbfi", + .description = "Split rendering option: bfi file", + }, + { + .id = CmdLnOptionId_noDelayCmp, + .match = "no_delay_compensation", + .matchShort = "no_delay_cmp", + .description = "[flag] Turn off delay compensation", + }, + { + .id = CmdLnOptionId_complexityLevel, + .match = "complexity_level", + .matchShort = "level", + .description = "Complexity level, level = (1, 2, 3), will be defined after characterisation.", + }, + { + .id = CmdLnOptionId_quietModeEnabled, + .match = "quiet", + .matchShort = "q", + .description = "[flag] Limit printouts to terminal", + }, + { + .id = CmdLnOptionId_listFormats, + .match = "list", + .matchShort = "l", + .description = "List supported audio formats", + }, + { + .id = CmdLnOptionId_framing, + .match = "framing", + .matchShort = "fr", + .description = "Set Render audio framing.", + }, +}; + + +/*------------------------------------------------------------------------------------------* + * Local function prototypes + *------------------------------------------------------------------------------------------*/ + +static const int32_t numCliOptions = sizeof( cliOptions ) / sizeof( CmdLnParser_Option ); + +static void printSupportedAudioConfigs( void ); + +static IVAS_AUDIO_CONFIG parseAudioConfig( const char *configString ); + +static void convertOutputBuffer( const Word32 *fixedBuffer, Word16 q, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer ); + +/*------------------------------------------------------------------------------------------* + * Local functions + *------------------------------------------------------------------------------------------*/ + +static ISAR_POST_REND_ReadOnlyAudioBuffer getReadOnlySubBuffer( + IVAS_REND_AudioBuffer buffer, + const int16_t chBeginIdx, + const int16_t numChannels ) +{ + ISAR_POST_REND_ReadOnlyAudioBuffer subBuffer; + + subBuffer.config = buffer.config; + subBuffer.config.numChannels = numChannels; + subBuffer.data_fx = buffer.data_fx + subBuffer.config.numSamplesPerChannel * chBeginIdx; + + return subBuffer; +} + + +static int16_t getTotalNumInChannels( + ISAR_POST_REND_HANDLE hIsarPostRend, + ISAR_POST_REND_InputId splitBinIds[RENDERER_MAX_BIN_INPUTS] ) +{ + int16_t totalNumInChannels = 0; + int16_t i, numInputChannels; + ivas_error error; + + for ( i = 0; i < RENDERER_MAX_BIN_INPUTS; ++i ) + { + if ( splitBinIds[i] == 0 ) + { + /* Skip inactive inputs */ + continue; + } + + if ( ( error = ISAR_POST_REND_GetInputNumChannels( hIsarPostRend, splitBinIds[i], &numInputChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + totalNumInChannels += numInputChannels; + } + + return totalNumInChannels; +} + +/*------------------------------------------------------------------------------------------* + * Local functions + *------------------------------------------------------------------------------------------*/ + +static const CmdLnParser_Option *findOptionById( + const int32_t id ) +{ + for ( int32_t i = 0; i < numCliOptions; ++i ) + { + if ( cliOptions[i].id == id ) + { + return &cliOptions[i]; + } + } + + return NULL; +} + +static bool parseInConfig( + const char *inFormatStr, + InputConfig *inConfig, + bool *sceneDescriptionInput ) +{ + char charBuf[FILENAME_MAX]; + + /* Initialize input config struct */ + inConfig->numBinBuses = 0; + + /* First check if input is being set to scene description file - this is not covered by parseAudioConfig(). */ + strncpy( charBuf, inFormatStr, sizeof( charBuf ) - 1 ); + charBuf[sizeof( charBuf ) - 1] = '\0'; + to_upper( charBuf ); + if ( strcmp( charBuf, "META" ) == 0 ) + { + *sceneDescriptionInput = true; + /* Parsing the file will be done later. At this point the actual file path + * may not be known as command line parameters are still being parsed. */ + return true; + } + + /* Check for single-format inputs. The given string should map to a member of AUDIO_CONFIG enum. */ + IVAS_AUDIO_CONFIG audioConfig = parseAudioConfig( inFormatStr ); + switch ( audioConfig ) + { + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + inConfig->numBinBuses = 1; + inConfig->binBuses[0].audioConfig = audioConfig; + inConfig->binBuses[0].inputChannelIndex = 0; + inConfig->binBuses[0].gain_dB = 0.0f; + break; + default: + { + /* Default case covers formats that are defined in the AUDIO_CONFIG enum, + * but cannot be used at input, e.g. BINAURAL */ + const CmdLnParser_Option *listOption = findOptionById( CmdLnOptionId_listFormats ); + fprintf( stderr, "Unsupported input format: %s. To list valid formats, use option --%s.\n", inFormatStr, listOption->match ); + return false; + } + } + + return true; +} + + +static bool parseRenderFramesize( + char *value, + IVAS_RENDER_FRAMESIZE *render_framesize ) +{ + int32_t tmp; + + *render_framesize = IVAS_RENDER_FRAMESIZE_UNKNOWN; + if ( !is_digits_only( value ) ) + { + return false; + } + tmp = (int32_t) strtol( value, NULL, 0 ); + switch ( (int16_t) tmp ) + { + case 5: + *render_framesize = IVAS_RENDER_FRAMESIZE_5MS; + break; + case 10: + *render_framesize = IVAS_RENDER_FRAMESIZE_10MS; + break; + case 20: + *render_framesize = IVAS_RENDER_FRAMESIZE_20MS; + break; + default: + return false; + } + + return true; +} + + +static IVAS_AUDIO_CONFIG parseAudioConfig( + const char *configString ) +{ + char charBuf[25]; + charBuf[24] = '\0'; + + strncpy( charBuf, configString, sizeof( charBuf ) - 1 ); + charBuf[sizeof( charBuf ) - 1] = '\0'; + to_upper( charBuf ); + + if ( strcmp( charBuf, "BINAURAL" ) == 0 ) + { + return IVAS_AUDIO_CONFIG_BINAURAL; + } + if ( strcmp( charBuf, "BINAURAL_SPLIT_PCM" ) == 0 ) + { + return IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM; + } + if ( strcmp( charBuf, "BINAURAL_SPLIT_CODED" ) == 0 ) + { + return IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED; + } + return IVAS_AUDIO_CONFIG_INVALID; +} + + +static bool checkRequiredArgs( + CmdlnArgs args ) +{ + const CmdLnParser_Option *tmpOption; + + /* Check required arguments */ + bool missingRequiredArg = false; + if ( isEmptyString( args.inputFilePath ) ) + { + tmpOption = findOptionById( CmdLnOptionId_inputFile ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + + const bool singleInputSpecified = ( args.inConfig.numBinBuses != 0 ); + + if ( !args.sceneDescriptionInput && !singleInputSpecified ) + { + /* Neither scene description input nor single-type input was specified on command line */ + tmpOption = findOptionById( CmdLnOptionId_inputFormat ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + if ( isEmptyString( args.outputFilePath ) ) + { + tmpOption = findOptionById( CmdLnOptionId_outputFile ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + if ( args.sampleRate == 0 ) + { + tmpOption = findOptionById( CmdLnOptionId_sampleRate ); + fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort ); + missingRequiredArg = true; + } + if ( missingRequiredArg ) + { + CmdLnParser_printUsage( args.executableName, cliOptions, numCliOptions ); + } + + return !missingRequiredArg; +} + +static CmdlnArgs defaultArgs( + const char *executableName ) +{ + CmdlnArgs args; + + strncpy( args.executableName, executableName, POST_REND_MAX_CLI_ARG_LENGTH ); + clearString( args.inputFilePath ); + clearString( args.outputFilePath ); + args.sampleRate = 0; + + args.outConfig.audioConfig = IVAS_AUDIO_CONFIG_INVALID; + + for ( int32_t i = 0; i < RENDERER_MAX_ISAR_MD_INPUTS; ++i ) + { + clearString( args.inMetadataFilePaths[i] ); + } + args.numInMetadataFiles = 0; + + clearString( args.headRotationFilePath ); + clearString( args.splitRendBFIFilePath ); + + args.delayCompensationEnabled = true; + args.quietModeEnabled = false; + args.sceneDescriptionInput = false; + + args.render_framesize = IVAS_RENDER_FRAMESIZE_20MS; + + return args; +} + +static void parseOption( + const int32_t optionId, + char **optionValues, + const int16_t numOptionValues, + void *pOutputStruct ) +{ + CmdlnArgs *args = pOutputStruct; + + switch ( optionId ) + { + case CmdLnOptionId_listFormats: + assert( numOptionValues == 0 ); + printSupportedAudioConfigs(); + exit( 0 ); + case CmdLnOptionId_inputFile: + assert( numOptionValues == 1 ); + strncpy( args->inputFilePath, optionValues[0], POST_REND_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_inputFormat: + assert( numOptionValues == 1 ); + if ( !parseInConfig( optionValues[0], &args->inConfig, &args->sceneDescriptionInput ) ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + break; + case CmdLnOptionId_inputMetadata: + assert( numOptionValues <= RENDERER_MAX_ISAR_MD_INPUTS ); + for ( int16_t i = 0; i < numOptionValues; ++i ) + { + strncpy( args->inMetadataFilePaths[i], optionValues[i], POST_REND_MAX_CLI_ARG_LENGTH - 1 ); + } + args->numInMetadataFiles = numOptionValues; + break; + case CmdLnOptionId_outputFile: + assert( numOptionValues == 1 ); + strncpy( args->outputFilePath, optionValues[0], POST_REND_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_sampleRate: + assert( numOptionValues == 1 ); + args->sampleRate = (int32_t) ( strtol( optionValues[0], NULL, 10 ) * 1000 ); + if ( args->sampleRate == 0 ) + { + fprintf( stderr, "Invalid sampling rate specified\n" ); + exit( -1 ); + } + break; + case CmdLnOptionId_trajFile: + assert( numOptionValues == 1 ); + strncpy( args->headRotationFilePath, optionValues[0], POST_REND_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_SplitRendBFIFile: + assert( numOptionValues == 1 ); + strncpy( args->splitRendBFIFilePath, optionValues[0], POST_REND_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_complexityLevel: + assert( numOptionValues == 1 ); + args->complexityLevel = (int32_t) ( strtol( optionValues[0], NULL, 10 ) ); + if ( args->complexityLevel < ISAR_POST_REND_COMPLEXITY_LEVEL_ONE || args->complexityLevel > ISAR_POST_REND_COMPLEXITY_LEVEL_THREE ) + { + fprintf( stdout, "Invalid complexity level specified.\n" ); + exit( -1 ); + } + else if ( args->complexityLevel == ISAR_POST_REND_COMPLEXITY_LEVEL_ONE || args->complexityLevel == ISAR_POST_REND_COMPLEXITY_LEVEL_TWO ) + { + fprintf( stdout, "Complexity levels 1 and 2 will be defined after characterisation - default to level 3 (full functionality).\n" ); + } + break; + case CmdLnOptionId_noDelayCmp: + assert( numOptionValues == 0 ); + args->delayCompensationEnabled = false; + break; + case CmdLnOptionId_quietModeEnabled: + assert( numOptionValues == 0 ); + args->quietModeEnabled = true; + break; + case CmdLnOptionId_framing: + assert( numOptionValues == 1 ); + if ( !parseRenderFramesize( optionValues[0], &args->render_framesize ) ) + { + fprintf( stderr, "Unknown or invalid option for frame size: %s\n", optionValues[0] ); + exit( -1 ); + } + + break; + default: + assert( 0 && "This should be unreachable - all command line options should be explicitly handled." ); + break; + } + + return; +} + +static CmdlnArgs parseCmdlnArgs( + const int argc, + char **argv ) +{ + CmdlnArgs args = defaultArgs( argv[0] ); + + if ( CmdLnParser_parseArgs( argc, argv, cliOptions, numCliOptions, &args, parseOption ) != 0 ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + + if ( !checkRequiredArgs( args ) ) + { + exit( -1 ); /* Error printout handled by failing function */ + } + + return args; +} + + +static void printSupportedAudioConfigs( void ) +{ + uint16_t i; + const char *supportedFormats[] = { + "BINAURAL (output only)", + "BINAURAL_SPLIT_PCM", + "BINAURAL_SPLIT_CODED", + }; + + fprintf( stdout, "Supported audio formats:\n" ); + for ( i = 0; i < sizeof( supportedFormats ) / sizeof( *supportedFormats ); i++ ) + { + fprintf( stdout, "%s\n", supportedFormats[i] ); + } + + return; +} + +/*--------------------------------------------------------------------------* + * convertInputBuffer() + * + * Convert input buffer from WAV/PCM file (int16_t, interleaved) to a format + * accepted by the renderer (float, packed) + *--------------------------------------------------------------------------*/ + +static void convertInputBuffer( + const int16_t *intBuffer, + const int16_t numIntSamplesPerChannel, + const int16_t numFloatSamplesPerChannel, + const int16_t numChannels, + Word32 *fixedBuffer ) +{ + int16_t chnl, smpl, i; + + i = 0; + + FOR( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + { + FOR( chnl = 0; chnl < numChannels; ++chnl ) + { + IF( i < numIntSamplesPerChannel ) + { + fixedBuffer[chnl * numFloatSamplesPerChannel + smpl] = (Word32) intBuffer[i]; + } + ELSE + { + fixedBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0; + } + + ++i; + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * convertOutputBuffer() + * + * Convert output buffer from the renderer (float, packed) to a format ready + * for writing to a WAV/PCM file (int16_t, interleaved) + *--------------------------------------------------------------------------*/ + +static void convertOutputBuffer( + const Word32 *fixedBuffer, + Word16 q, + const int16_t numSamplesPerChannel, + const int16_t numChannels, + int16_t *intBuffer ) +{ + int16_t chnl, smpl, i; + Word32 temp; + + i = 0; + + for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + temp = L_shr_r( fixedBuffer[chnl * numSamplesPerChannel + smpl], q ); + IF( GT_32( temp, ISAR_MAX16B_FX ) ) + { + temp = ISAR_MAX16B_FX; + } + ELSE IF( LT_32( temp, ISAR_MIN16B_FX ) ) + { + temp = ISAR_MIN16B_FX; + } + intBuffer[i] = (int16_t) temp; + + ++i; + } + } + + return; +} + +/*------------------------------------------------------------------------------------------* + * main() + * + * Main ISAR post renderer function for command-line interface + *------------------------------------------------------------------------------------------*/ + +int main( + int argc, + char **argv ) +{ + ISAR_POST_REND_HANDLE hIsarPostRend; + RotFileReader *headRotReader = NULL; + RotFileReader *externalOrientationFileReader = NULL; + SplitRendBFIFileReader *splitRendBFIReader = NULL; + AudioFileReader *audioReader = NULL; + AudioFileWriter *audioWriter; + int32_t inBufferSize; + int32_t outBufferSize; + int32_t bitsBufferSize; + int16_t *inpInt16Buffer; + Word32 *inFloatBuffer_fx; + int16_t *outInt16Buffer; + Word32 *outFloatBuffer_fx; + uint8_t *bitsBufferData = NULL; + IVAS_REND_AudioBuffer inBuffer; + IVAS_REND_AudioBuffer outBuffer; + ISAR_POST_REND_BitstreamBuffer bitsBuffer; + SplitFileReadWrite *hSplitRendFileReadWrite; + char audioFilePath[FILENAME_MAX]; + int16_t numSamplesRead; + int16_t delayNumSamples = -1; + int16_t delayNumSamples_orig = 0; + int16_t zeroPad = 0; + int16_t zeroPadToWrite = 0; + int32_t delayTimeScale = 0; + int16_t i, numChannels; + ivas_error error = IVAS_ERR_OK; + bool splitBinNeedsNewFrame = true; + +#ifdef WMOPS + reset_wmops(); + reset_mem( USE_BYTES ); +#endif + + hSplitRendFileReadWrite = NULL; + bitsBuffer.bits = NULL; + bitsBuffer.config.bitsRead = 0; + bitsBuffer.config.bitsWritten = 0; + bitsBuffer.config.bufLenInBytes = 0; + bitsBuffer.config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + bitsBuffer.config.poseCorrection = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + bitsBuffer.config.codec_frame_size_ms = 5; + bitsBuffer.config.isar_frame_size_ms = 20; + bitsBuffer.config.lc3plusHighRes = 0; +#else + bitsBuffer.config.codec_frame_size_ms = 20; +#endif + + + CmdlnArgs args = parseCmdlnArgs( argc, argv ); + + convert_backslash( args.inputFilePath ); + convert_backslash( args.outputFilePath ); + convert_backslash( args.headRotationFilePath ); + + if ( !isEmptyString( args.headRotationFilePath ) ) + { + if ( RotationFileReader_open( args.headRotationFilePath, &headRotReader ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", args.headRotationFilePath ); + exit( -1 ); + } + } + + if ( !isEmptyString( args.splitRendBFIFilePath ) ) + { + convert_backslash( args.splitRendBFIFilePath ); + SplitRendBFIFileReader_open( args.splitRendBFIFilePath, &splitRendBFIReader ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t inFileSampleRate = 0; +#endif + strncpy( audioFilePath, args.inputFilePath, FILENAME_MAX - 1 ); + hSplitRendFileReadWrite = NULL; + if ( ( args.inConfig.numBinBuses > 0 ) && ( args.inConfig.binBuses[0].audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + error = split_rend_reader_open( &hSplitRendFileReadWrite, + args.inMetadataFilePaths[0], + &bitsBuffer.config.codec, + &bitsBuffer.config.poseCorrection, + &bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + &bitsBuffer.config.isar_frame_size_ms, + &inFileSampleRate, + &bitsBuffer.config.lc3plusHighRes +#endif + ); + if ( error != IVAS_ERR_OK ) + { + fprintf( stderr, "Could not open split rend metadata file %s\n", args.inMetadataFilePaths[0] ); + exit( -1 ); + } + + if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening file: %s\n", audioFilePath ); + exit( -1 ); + } + } + + /*if split renderer is running in post renderer mode*/ + if ( ( args.inConfig.numBinBuses > 0 ) && ( args.inConfig.binBuses[0].audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) + { + error = split_rend_reader_open( &hSplitRendFileReadWrite, + args.inputFilePath, + &bitsBuffer.config.codec, + &bitsBuffer.config.poseCorrection, + &bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + &bitsBuffer.config.isar_frame_size_ms, + &inFileSampleRate, + &bitsBuffer.config.lc3plusHighRes +#endif + ); + if ( error != IVAS_ERR_OK ) + { + fprintf( stderr, "Could not open split rend metadata file %s\n", args.inputFilePath ); + exit( -1 ); + } + audioReader = NULL; + } + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t inFileSampleRate = 0; +#endif + if ( audioReader != NULL ) + { + error = AudioFileReader_getSamplingRate( audioReader, &inFileSampleRate ); + } + else +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( hSplitRendFileReadWrite == NULL ) +#endif + { + inFileSampleRate = args.sampleRate; + } + + switch ( error ) + { + case IVAS_ERR_OK: + /* If sampling rate not given on command line, use the one from SR file */ + if ( args.sampleRate == 0 ) + { + args.sampleRate = inFileSampleRate; + } + /* else if sampling rate given on command line, compare with wav file */ + else if ( inFileSampleRate != args.sampleRate ) + { + fprintf( stderr, "Sampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n", args.sampleRate, inFileSampleRate, args.inputFilePath ); + exit( -1 ); + } + break; + case IVAS_ERR_SAMPLING_RATE_UNKNOWN: /* Returned when input is raw PCM */ + if ( args.sampleRate == 0 ) + { + fprintf( stderr, "Sampling rate must be specified on command line when using raw PCM input\n" ); + exit( -1 ); + } + break; + default: + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + int16_t inFileNumChannels = 0; + if ( audioReader != NULL ) + { + error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); + if ( error != IVAS_ERR_OK && error != IVAS_ERR_NUM_CHANNELS_UNKNOWN ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + const int16_t frameSize_smpls = (int16_t) ( ( args.render_framesize ) * args.sampleRate * 5 / ( 1000 ) ); + args.outConfig.audioConfig = IVAS_AUDIO_CONFIG_BINAURAL; + if ( ( error = ISAR_POST_REND_open( &hIsarPostRend, args.sampleRate, args.outConfig.audioConfig, true, 0, 0, (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error opening renderer handle: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + /* === Configure === */ + if ( ( error = ISAR_POST_REND_InitConfig( hIsarPostRend, args.outConfig.audioConfig ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in Renderer Config Init: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + if ( args.inConfig.numBinBuses > 0 ) + { + if ( ( error = ISAR_REND_SetSplitRendBitstreamHeader( hIsarPostRend, + bitsBuffer.config.codec, + bitsBuffer.config.poseCorrection, + bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + bitsBuffer.config.isar_frame_size_ms, + bitsBuffer.config.lc3plusHighRes +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in getting split renderer bitstream header: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + + ISAR_POST_REND_InputId splitBinIds[RENDERER_MAX_BIN_INPUTS]; + + for ( i = 0; i < RENDERER_MAX_BIN_INPUTS; i++ ) + { + splitBinIds[i] = 0u; + } + + for ( i = 0; i < args.inConfig.numBinBuses; ++i ) + { + if ( ( error = ISAR_POST_REND_AddInput( hIsarPostRend, args.inConfig.binBuses[i].audioConfig, &splitBinIds[i] ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + const int16_t totalNumInChannels = getTotalNumInChannels( hIsarPostRend, splitBinIds ); + + if ( inFileNumChannels != 0 /* inFileNumChannels is 0 with raw PCM input */ && totalNumInChannels != inFileNumChannels ) + { + fprintf( stderr, "Number of channels in input file does not match selected configuration\n" ); + exit( -1 ); + } + + int16_t numOutChannels = 2; + + if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); + exit( -1 ); + } + + inBufferSize = frameSize_smpls * totalNumInChannels; + outBufferSize = frameSize_smpls * numOutChannels; + inpInt16Buffer = malloc( inBufferSize * sizeof( int16_t ) ); + memset( inpInt16Buffer, 0, inBufferSize * sizeof( int16_t ) ); + + inFloatBuffer_fx = malloc( inBufferSize * sizeof( Word32 ) ); + inBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + outFloatBuffer_fx = malloc( outBufferSize * sizeof( Word32 ) ); + outBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + + outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); + + inBuffer.config.is_cldfb = 0; + inBuffer.config.numChannels = (int16_t) totalNumInChannels; + inBuffer.data_fx = inFloatBuffer_fx; + inBuffer.q_data_fx = malloc( sizeof( Word16 ) ); + + outBuffer.config.is_cldfb = 0; + outBuffer.config.numChannels = (int16_t) numOutChannels; + outBuffer.data_fx = outFloatBuffer_fx; + outBuffer.q_data_fx = malloc( sizeof( Word16 ) ); + + memset( outBuffer.data_fx, 0, outBuffer.config.numSamplesPerChannel * outBuffer.config.numChannels * sizeof( Word32 ) ); + + bitsBufferSize = SPLIT_REND_BITS_BUFF_SIZE; + + if ( bitsBufferSize > 0 ) + { + bitsBufferData = malloc( bitsBufferSize * sizeof( uint8_t ) ); + } + else + { + bitsBufferData = NULL; + } + + bitsBuffer.bits = bitsBufferData; + bitsBuffer.config.bitsRead = 0; + bitsBuffer.config.bitsWritten = 0; + bitsBuffer.config.bufLenInBytes = bitsBufferSize; + +#ifdef WMOPS + reset_stack(); + reset_wmops(); +#endif + + if ( !args.quietModeEnabled ) + { + fprintf( stdout, "\n------ Running the ISAR post renderer ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else + { + fprintf( stdout, "\n\n-- Start the ISAR post renderer (quiet mode) --\n\n" ); + } + + while ( 1 ) + { + int16_t num_in_channels; + num_in_channels = inBuffer.config.numChannels; + + numSamplesRead = 0; + if ( ( hSplitRendFileReadWrite != NULL ) && splitBinNeedsNewFrame ) + { + ivas_error error_tmp; + numSamplesRead = (int16_t) inBufferSize; + error_tmp = split_rend_read_bits_from_file( hSplitRendFileReadWrite, bitsBuffer.bits, &bitsBuffer.config.bitsRead, &bitsBuffer.config.bitsWritten ); + if ( error_tmp != IVAS_ERR_OK ) + { + if ( error_tmp == IVAS_ERR_END_OF_FILE ) + { + numSamplesRead = 0; + } + else + { + fprintf( stderr, "\nUnable to read from bitstream file!\n" ); + exit( -1 ); + } + } + } + + if ( audioReader != NULL ) + { + /* Read the input data */ + if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError reading from file %s\n", audioFilePath ); + exit( -1 ); + } + } + + if ( numSamplesRead == 0 && splitBinNeedsNewFrame ) + { + /* end of input data */ + break; + } + + /* Convert from int to float and from interleaved to packed */ + convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer_fx ); + *inBuffer.q_data_fx = 0; + int16_t num_subframes, sf_idx; + num_subframes = (int16_t) args.render_framesize; + + /* Read from head rotation trajectory file if specified */ + if ( headRotReader != NULL ) + { + for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + IVAS_QUATERNION headRot; + IVAS_VECTOR3 Pos; + + IF( ( error = HeadRotationFileReading_fx( headRotReader, &headRot, &Pos ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + if ( ( error = ISAR_POST_REND_SetHeadRotation( hIsarPostRend, headRot, Pos, DEFAULT_AXIS, sf_idx ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error setting Head Rotation: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + } + else + { + fprintf( stderr, "Head Rotation should be enabled in post renderer\n" ); + exit( -1 ); + } + + /* Read from split renderer bfi file if specified */ + if ( splitRendBFIReader != NULL && splitBinNeedsNewFrame ) + { + int16_t bfi; + if ( ( error = SplitRendBFIFileReading( splitRendBFIReader, &bfi ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in SplitRendBFIFileReading(): %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + if ( ( error = ISAR_POST_REND_SetSplitRendBFI( hIsarPostRend, bfi ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in ISAR_POST_REND_SetSplitRendBFI(): %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + for ( i = 0; i < args.inConfig.numBinBuses; ++i ) + { + if ( numSamplesRead > 0 ) + { + if ( ( error = ISAR_POST_REND_GetInputNumChannels( hIsarPostRend, splitBinIds[i], &numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + ISAR_POST_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.binBuses[i].inputChannelIndex, numChannels ); + + if ( ( error = ISAR_POST_REND_FeedInputAudio( hIsarPostRend, splitBinIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + if ( splitBinNeedsNewFrame ) + { + if ( ( error = ISAR_POST_REND_FeedSplitBinauralBitstream( hIsarPostRend, splitBinIds[i], &bitsBuffer ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + } + + if ( ( error = ISAR_POST_REND_GetSplitBinauralSamples( hIsarPostRend, outBuffer, &splitBinNeedsNewFrame ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + + int16_t num_out_channels; + num_out_channels = outBuffer.config.numChannels; + + /* Convert from float to int and from packed to interleaved. + * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ + convertOutputBuffer( outFloatBuffer_fx, *outBuffer.q_data_fx, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); + + if ( delayNumSamples == -1 ) + { + if ( args.delayCompensationEnabled ) + { + if ( ISAR_POST_REND_GetDelay( hIsarPostRend, &delayNumSamples, &delayTimeScale ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get delay of renderer!\n" ); + exit( -1 ); + } + + if ( hSplitRendFileReadWrite != NULL ) + { + uint32_t pre_rend_delay_ns; + split_rend_read_pre_rend_delay_ns( hSplitRendFileReadWrite, &pre_rend_delay_ns ); + delayNumSamples += (Word16) ( ( ( (Word64) pre_rend_delay_ns * delayTimeScale ) + 500000000 ) / 1000000000 ); + } + + delayNumSamples_orig = delayNumSamples; + } + else + { + delayNumSamples = 0; + } + zeroPad = delayNumSamples; + } + + if ( audioWriter != NULL ) + { + if ( delayNumSamples * num_out_channels < outBufferSize ) + { + if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); + exit( -1 ); + } + delayNumSamples = 0; + } + else + { + delayNumSamples -= (int16_t) ( outBufferSize / num_out_channels ); + } + } + + bitsBuffer.config.bitsRead = 0; + bitsBuffer.config.bitsWritten = 0; + + frame++; + if ( !args.quietModeEnabled ) + { + fprintf( stdout, "%-8d\b\b\b\b\b\b\b\b", frame ); + } + +#ifdef WMOPS + update_mem(); + update_wmops(); +#endif + } + + /* add zeros at the end to have equal length of synthesized signals */ + if ( audioWriter != NULL ) + { + for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) + { + memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + exit( -1 ); + } + } + + memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + exit( -1 ); + } + zeroPadToWrite = 0; + } + + if ( !args.quietModeEnabled && args.delayCompensationEnabled ) + { + fprintf( stdout, "\nRenderer delay: %-5u [samples] - Timescale: %5u\n", delayNumSamples_orig, delayTimeScale ); + } + + fprintf( stdout, "\n\nRendering of %d frames finished\n\n", frame ); + +#ifdef DEBUGGING + int32_t cnt_frames_limited, noClipping; + if ( ( cnt_frames_limited = ISAR_POST_REND_GetCntFramesLimited( hIsarPostRend ) ) > 0 ) + { + fprintf( stdout, "Limiter applied in %d frames.\n\n", cnt_frames_limited ); + } + if ( ( noClipping = ISAR_POST_REND_GetNoCLipping( hIsarPostRend ) ) > 0 ) + { + fprintf( stdout, "Clipping (saturation) detected: %d samples clipped!!!\n\n", noClipping ); + } +#endif + + /* === Close === */ + free( inpInt16Buffer ); + free( inFloatBuffer_fx ); + free( inBuffer.q_data_fx ); + free( outInt16Buffer ); + free( outFloatBuffer_fx ); + free( outBuffer.q_data_fx ); + + if ( bitsBufferData != NULL ) + { + free( bitsBufferData ); + } + + split_rend_reader_writer_close( &hSplitRendFileReadWrite ); + SplitRendBFIFileReader_close( &splitRendBFIReader ); + + AudioFileReader_close( &audioReader ); + AudioFileWriter_close( &audioWriter ); + RotationFileReader_close( &headRotReader ); + RotationFileReader_close( &externalOrientationFileReader ); + + ISAR_POST_REND_Close( &hIsarPostRend ); + +#ifdef DEBUGGING + dbgclose(); +#endif +#ifdef WMOPS + print_wmops(); + print_mem( NULL ); +#endif + + return 0; +} + + +#undef WMC_TOOL_SKIP + +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/apps/renderer.c b/apps/renderer.c index f5c0a8847..9b64aff93 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -45,6 +45,10 @@ #include "masa_file_writer.h" #include "render_config_reader.h" #include "rotation_file_reader.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "split_render_file_read_write.h" +#include "split_rend_bfi_file_reader.h" +#endif #include "vector3_pair_file_reader.h" #include "wmc_auto.h" @@ -148,7 +152,13 @@ typedef struct OutputConfig outConfig; char inMetadataFilePaths[RENDERER_MAX_ISM_INPUTS][RENDERER_MAX_CLI_ARG_LENGTH]; int16_t numInMetadataFiles; +#ifdef SPLIT_REND_WITH_HEAD_ROT + char outMetadataFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; +#endif char headRotationFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + char splitRendBFIFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; +#endif char referenceVectorFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; char referenceRotationFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; char externalOrientationFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; @@ -195,6 +205,10 @@ typedef enum CmdLnOptionId_inputMetadata, CmdLnOptionId_listFormats, CmdLnOptionId_inputGain, +#ifdef SPLIT_REND_WITH_HEAD_ROT + CmdLnOptionId_outputMetadata, + CmdLnOptionId_SplitRendBFIFile, +#endif CmdLnOptionId_referenceVectorFile, CmdLnOptionId_exteriorOrientationFile, CmdLnOptionId_framing, @@ -220,7 +234,11 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_inputMetadata, .match = "input_metadata", .matchShort = "im", +#ifdef SPLIT_REND_WITH_HEAD_ROT + .description = "Space-separated list of path to metadata files for ISM or MASA inputs or BINAURAL_SPLIT_PCM input mode", +#else .description = "Space-separated list of path to metadata files for ISM or MASA inputs", +#endif }, { .id = CmdLnOptionId_outputFile, @@ -246,6 +264,20 @@ static const CmdLnParser_Option cliOptions[] = { .matchShort = "T", .description = "Head rotation trajectory file for simulation of head tracking (only for binaural outputs)", }, +#ifdef SPLIT_REND_WITH_HEAD_ROT + { + .id = CmdLnOptionId_outputMetadata, + .match = "output_metadata", + .matchShort = "om", + .description = "coded metadata file for BINAURAL_SPLIT_PCM output mode", + }, + { + .id = CmdLnOptionId_SplitRendBFIFile, + .match = "post_rend_bfi_file", + .matchShort = "prbfi", + .description = "Split rendering option: bfi file", + }, +#endif { .id = CmdLnOptionId_refRotFile, .match = "reference_rotation_file", @@ -403,11 +435,19 @@ static void printSupportedAudioConfigs( void ); static IVAS_AUDIO_CONFIG parseAudioConfig( const char *configString ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna ); + +static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn ); +static void convertOutputBuffer_fx( const Word32 *Word32Buffer, const Word16 numSamplesPerChannel, const Word16 numChannels, Word16 *intBuffer, Word16 q_factor, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn ); +static void convertInputBuffer_fx( const Word16 *intBuffer, const Word16 numIntSamplesPerChannel, const Word16 numFloatSamplesPerChannel, const Word16 numChannels, Word32 *Int32Buffer, Word16 in_q_factor, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna ); +#else static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer ); static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer ); static void convertOutputBuffer_fx( const Word32 *Word32Buffer, const Word16 numSamplesPerChannel, const Word16 numChannels, Word16 *intBuffer, Word16 q_factor ); static void convertInputBuffer_fx( const Word16 *intBuffer, const Word16 numIntSamplesPerChannel, const Word16 numFloatSamplesPerChannel, const Word16 numChannels, Word32 *Int32Buffer, Word16 in_q_factor ); +#endif /*------------------------------------------------------------------------------------------* @@ -593,6 +633,44 @@ static float dBToLin( } +#ifdef SPLIT_REND_WITH_HEAD_ROT +static int16_t get_cldfb_in_flag( + const IVAS_AUDIO_CONFIG audioConfig, + const IVAS_RENDER_CONFIG_DATA *renderConfig ) +{ + int16_t cldfb_in_flag; + + cldfb_in_flag = 0; + if ( renderConfig->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + { +#ifdef DEBUGGING + cldfb_in_flag = 1; +#endif + if ( audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + cldfb_in_flag = 1; + } + } + + return cldfb_in_flag; +} + +static int16_t is_split_pre_rend_mode( + CmdlnArgs *args ) +{ + int16_t flag; + + flag = 0; + if ( args->outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || args->outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + flag = 1; + } + + return flag; +} +#endif + + /*------------------------------------------------------------------------------------------* * main() * @@ -607,6 +685,12 @@ int main( RotFileReader *headRotReader = NULL; RotFileReader *externalOrientationFileReader = NULL; RotFileReader *referenceRotReader = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS]; + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_INPUT_CHANNELS]; + int16_t cldfb_in_flag, CLDFBframeSize_smpls; + SplitRendBFIFileReader *splitRendBFIReader = NULL; +#endif Vector3PairFileReader *referenceVectorReader = NULL; hrtfFileReader *hrtfFileReader = NULL; IsmPositionProvider *positionProvider; @@ -620,6 +704,9 @@ int main( AudioFileWriter *audioWriter; int32_t inBufferSize; int32_t outBufferSize; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int32_t bitsBufferSize; +#endif int16_t *inpInt16Buffer; float *inFloatBuffer; int16_t *outInt16Buffer; @@ -627,8 +714,17 @@ int main( Word32 *inInt32Buffer; Word32 gain_fx; float *outFloatBuffer; +#ifdef SPLIT_REND_WITH_HEAD_ROT + uint8_t *bitsBufferData = NULL; +#endif IVAS_REND_AudioBuffer inBuffer; IVAS_REND_AudioBuffer outBuffer; +#ifdef SPLIT_REND_WITH_HEAD_ROT + IVAS_REND_BitstreamBuffer bitsBuffer; + SplitFileReadWrite *hSplitRendFileReadWrite; + int16_t delayNumSamples_temp; + int32_t delayTimeScale_temp; +#endif int16_t numSamplesRead; int16_t delayNumSamples = -1; int16_t delayNumSamples_orig = 0; @@ -637,7 +733,6 @@ int main( int32_t delayTimeScale = 0; int16_t i, numChannels; ivas_error error = IVAS_ERR_OK; - bool splitBinNeedsNewFrame = true; #ifdef WMOPS reset_wmops(); @@ -650,6 +745,24 @@ int main( hMasaMetadata[i] = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + hSplitRendFileReadWrite = NULL; + CLDFBframeSize_smpls = 0; + cldfb_in_flag = 0; + bitsBuffer.bits = NULL; + bitsBuffer.config.bitsRead = 0; + bitsBuffer.config.bitsWritten = 0; + bitsBuffer.config.bufLenInBytes = 0; + bitsBuffer.config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + bitsBuffer.config.poseCorrection = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + bitsBuffer.config.codec_frame_size_ms = 5; + bitsBuffer.config.isar_frame_size_ms = 20; + bitsBuffer.config.lc3plus_highres = 0; +#else + bitsBuffer.config.codec_frame_size_ms = 20; +#endif +#endif for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) { lfeRoutingConfigs[i] = NULL; @@ -710,6 +823,13 @@ int main( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( !isEmptyString( args.splitRendBFIFilePath ) ) + { + convert_backslash( args.splitRendBFIFilePath ); + SplitRendBFIFileReader_open( args.splitRendBFIFilePath, &splitRendBFIReader ); + } +#endif if ( !isEmptyString( args.externalOrientationFilePath ) ) { if ( RotationFileReader_open( args.externalOrientationFilePath, &externalOrientationFileReader ) != IVAS_ERR_OK ) @@ -877,16 +997,28 @@ int main( IVAS_RENDER_CONFIG_DATA renderConfig; /* sanity check */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && !is_split_pre_rend_mode( &args ) ) + { + fprintf( stderr, "\nExternal Renderer Config is supported only when binaural output configurations is used as output OR when Split pre-rendering mode is enabled. Exiting. \n" ); + exit( -1 ); + } +#else if ( ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) { fprintf( stderr, "\nExternal Renderer Config is only supported for binaural output configurations. Exiting. \n" ); exit( -1 ); } +#endif if ( ( error = IVAS_REND_GetRenderConfig( hIvasRend, &renderConfig ) ) != IVAS_ERR_OK ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed: %s\n", ivas_error_to_string( error ) ); +#else fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed\n" ); +#endif exit( -1 ); } @@ -914,11 +1046,28 @@ int main( renderConfig.roomAcoustics.override = 1; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* ISAR frame size is set from command line, not renderer config file. + * This will be ignored if output format is not split rendering. */ + renderConfig.split_rend_config.isar_frame_size_ms = (int16_t) args.render_framesize /* given in number of 5ms subframes */ * 5; +#endif +#endif + if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + fprintf( stderr, "\nIVAS_REND_FeedRenderConfig failed: %s\n", ivas_error_to_string( error ) ); +#else fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed\n" ); +#endif exit( -1 ); } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + CLDFBframeSize_smpls = frameSize_smpls * 2; + cldfb_in_flag = get_cldfb_in_flag( args.outConfig.audioConfig, &renderConfig ); +#endif } if ( ( error = IVAS_REND_SetOrientationTrackingMode( hIvasRend, args.orientation_tracking ) ) != IVAS_ERR_OK ) @@ -1173,17 +1322,160 @@ int main( exit( -1 ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( cldfb_in_flag ) + { + if ( ( error = IVAS_REND_openCldfb( cldfbAna, cldfbSyn, totalNumInChannels, numOutChannels, args.sampleRate ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error in IVAS_REND_openCldfb(): %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + + IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, + &bitsBuffer.config.codec, + &bitsBuffer.config.poseCorrection, + &bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + &bitsBuffer.config.isar_frame_size_ms +#endif + ); + + if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get delay of renderer!\n" ); + exit( -1 ); + } + + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, + args.outputFilePath, + delayNumSamples_temp, + delayTimeScale_temp, + bitsBuffer.config.codec, + bitsBuffer.config.poseCorrection, + bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + bitsBuffer.config.isar_frame_size_ms, + args.sampleRate, + bitsBuffer.config.lc3plus_highres +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Could not open split rend metadata file %s\n", args.outputFilePath ); + exit( -1 ); + } + audioWriter = NULL; + } + else + { + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + + IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, + &bitsBuffer.config.codec, + &bitsBuffer.config.poseCorrection, + &bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + &bitsBuffer.config.isar_frame_size_ms +#endif + ); + + if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to get delay of renderer!\n" ); + exit( -1 ); + } + + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, + args.outMetadataFilePath, + delayNumSamples_temp, + delayTimeScale_temp, + bitsBuffer.config.codec, + bitsBuffer.config.poseCorrection, + bitsBuffer.config.codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + bitsBuffer.config.isar_frame_size_ms, + args.sampleRate, + bitsBuffer.config.lc3plus_highres +#endif + ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Could not open split rend metadata file %s\n", args.outMetadataFilePath ); + exit( -1 ); + } + } +#endif if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) { fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); exit( -1 ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif inBufferSize = frameSize_smpls * totalNumInChannels; outBufferSize = frameSize_smpls * numOutChannels; inpInt16Buffer = malloc( inBufferSize * sizeof( int16_t ) ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( cldfb_in_flag == 0 ) + { + inFloatBuffer = malloc( inBufferSize * sizeof( float ) ); + inBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + outFloatBuffer = malloc( outBufferSize * sizeof( float ) ); + outBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + } + else + { + inFloatBuffer = malloc( CLDFBframeSize_smpls * totalNumInChannels * sizeof( float ) ); + inBuffer.config.numSamplesPerChannel = (int16_t) CLDFBframeSize_smpls; + outFloatBuffer = malloc( CLDFBframeSize_smpls * totalNumInChannels * sizeof( float ) ); + outBuffer.config.numSamplesPerChannel = (int16_t) CLDFBframeSize_smpls; + } + outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); + + inBuffer.config.is_cldfb = cldfb_in_flag; + inBuffer.config.numChannels = (int16_t) totalNumInChannels; + inBuffer.data = inFloatBuffer; + + outBuffer.config.is_cldfb = cldfb_in_flag; + outBuffer.config.numChannels = (int16_t) numOutChannels; + outBuffer.data = outFloatBuffer; + + memset( outBuffer.data, 0, outBuffer.config.numSamplesPerChannel * outBuffer.config.numChannels * sizeof( float ) ); + + if ( is_split_pre_rend_mode( &args ) ) + { + bitsBufferSize = SPLIT_REND_BITS_BUFF_SIZE; + } + else + { + bitsBufferSize = 0; + } + + if ( bitsBufferSize > 0 ) + { + bitsBufferData = malloc( bitsBufferSize * sizeof( uint8_t ) ); + } + else + { + bitsBufferData = NULL; + } + + bitsBuffer.bits = bitsBufferData; + bitsBuffer.config.bitsRead = 0; + bitsBuffer.config.bitsWritten = 0; + bitsBuffer.config.bufLenInBytes = bitsBufferSize; +#else inFloatBuffer = malloc( inBufferSize * sizeof( float ) ); outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); outInt32Buffer = malloc( outBufferSize * sizeof( Word32 ) ); @@ -1197,6 +1489,8 @@ int main( outBuffer.config.numChannels = (int16_t) numOutChannels; outBuffer.data_fx = outInt32Buffer; inBuffer.data_fx = inInt32Buffer; +#endif + #ifdef WMOPS reset_stack(); reset_wmops(); @@ -1222,6 +1516,8 @@ int main( num_in_channels = inBuffer.config.numChannels; const bool isCurrentFrameMultipleOf20ms = frame % ( 4 / args.render_framesize ) == 0; + numSamplesRead = 0; + /* Read the input data */ if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) { @@ -1229,14 +1525,18 @@ int main( exit( -1 ); } - if ( numSamplesRead == 0 && splitBinNeedsNewFrame ) + if ( numSamplesRead == 0 ) { /* end of input data */ break; } /* Convert from int to float and from interleaved to packed */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); +#else convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer ); +#endif *outBuffer.pq_fact = 16 - ( gd_bits ); convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, *outBuffer.pq_fact ); int16_t num_subframes, sf_idx; @@ -1295,7 +1595,11 @@ int main( exit( -1 ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = IVAS_REND_SetHeadRotation( hIvasRend, headRot, Pos, DEFAULT_AXIS, sf_idx ) ) != IVAS_ERR_OK ) +#else if ( ( error = IVAS_REND_SetHeadRotation( hIvasRend, headRot, Pos, sf_idx ) ) != IVAS_ERR_OK ) +#endif { fprintf( stderr, "Error setting Head Rotation: %s\n", ivas_error_to_string( error ) ); exit( -1 ); @@ -1448,19 +1752,43 @@ int main( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( ( error = IVAS_REND_GetSplitBinauralBitstream( hIvasRend, outBuffer, &bitsBuffer ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); + exit( -1 ); + } + } + else + { +#endif if ( ( error = IVAS_REND_GetSamples( hIvasRend, outBuffer ) ) != IVAS_ERR_OK ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + fprintf( stderr, "Error %s\n", ivas_error_to_string( error ) ); +#else fprintf( stderr, "Error in getting samples\n" ); +#endif exit( -1 ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif int16_t num_out_channels; num_out_channels = outBuffer.config.numChannels; + /* Convert from float to int and from packed to interleaved. * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ if ( *outBuffer.pq_fact == 0 ) { - convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); + #ifdef SPLIT_REND_WITH_HEAD_ROT + convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, cldfb_in_flag, cldfbSyn ); +#else + convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); +#endif } else { @@ -1486,6 +1814,20 @@ int main( zeroPad = delayNumSamples; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( is_split_pre_rend_mode( &args ) ) + { + if ( split_rend_write_bitstream_to_file( hSplitRendFileReadWrite, bitsBuffer.bits, &bitsBuffer.config.bitsRead, + &bitsBuffer.config.bitsWritten ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to write to bitstream file!\n" ); + exit( -1 ); + } + } + + if ( audioWriter != NULL ) + { +#endif if ( delayNumSamples * num_out_channels < outBufferSize ) { if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) @@ -1500,6 +1842,14 @@ int main( delayNumSamples -= (int16_t) ( outBufferSize / num_out_channels ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } + + bitsBuffer.config.bitsRead = 0; + bitsBuffer.config.bitsWritten = 0; +#endif + + /* Write MASA metadata for MASA outputs */ if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA1 || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) { @@ -1603,6 +1953,10 @@ int main( } /* add zeros at the end to have equal length of synthesized signals */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( audioWriter != NULL ) + { +#endif for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) { memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); @@ -1620,6 +1974,9 @@ int main( exit( -1 ); } zeroPadToWrite = 0; +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif if ( args.inConfig.numAudioObjects != 0 && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) @@ -1642,11 +1999,27 @@ int main( free( outFloatBuffer ); free( outInt32Buffer ); free( inInt32Buffer ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( bitsBufferData != NULL ) + { + free( bitsBufferData ); + } +#endif for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) { MasaFileReader_close( &masaReaders[i] ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( cldfb_in_flag ) + { + IVAS_REND_closeCldfb( cldfbAna, cldfbSyn ); + } + + split_rend_reader_writer_close( &hSplitRendFileReadWrite ); + SplitRendBFIFileReader_close( &splitRendBFIReader ); +#endif for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) { @@ -1946,8 +2319,13 @@ static bool parseOrientationTracking( static IVAS_AUDIO_CONFIG parseAudioConfig( const char *configString ) { +#ifndef SPLIT_REND_WITH_HEAD_ROT char charBuf[21]; charBuf[20] = '\0'; +#else + char charBuf[25]; + charBuf[24] = '\0'; +#endif strncpy( charBuf, configString, sizeof( charBuf ) - 1 ); charBuf[sizeof( charBuf ) - 1] = '\0'; @@ -2022,6 +2400,16 @@ static IVAS_AUDIO_CONFIG parseAudioConfig( { return IVAS_AUDIO_CONFIG_BINAURAL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( strcmp( charBuf, "BINAURAL_SPLIT_PCM" ) == 0 ) + { + return IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM; + } + if ( strcmp( charBuf, "BINAURAL_SPLIT_CODED" ) == 0 ) + { + return IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED; + } +#endif if ( strcmp( charBuf, "BINAURAL_ROOM_IR" ) == 0 ) { return IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR; @@ -2154,6 +2542,10 @@ static CmdlnArgs defaultArgs( args.numInMetadataFiles = 0; clearString( args.headRotationFilePath ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + clearString( args.outMetadataFilePath ); + clearString( args.splitRendBFIFilePath ); +#endif clearString( args.referenceVectorFilePath ); clearString( args.referenceRotationFilePath ); clearString( args.customHrtfFilePath ); @@ -2246,6 +2638,16 @@ static void parseOption( assert( numOptionValues == 1 ); strncpy( args->headRotationFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); break; +#ifdef SPLIT_REND_WITH_HEAD_ROT + case CmdLnOptionId_outputMetadata: + assert( numOptionValues == 1 ); + strncpy( args->outMetadataFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; + case CmdLnOptionId_SplitRendBFIFile: + assert( numOptionValues == 1 ); + strncpy( args->splitRendBFIFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); + break; +#endif case CmdLnOptionId_referenceVectorFile: assert( numOptionValues == 1 ); strncpy( args->referenceVectorFilePath, optionValues[0], RENDERER_MAX_CLI_ARG_LENGTH - 1 ); @@ -3264,6 +3666,10 @@ static void printSupportedAudioConfigs( void ) "ISMx (input only)", "MASAx", "BINAURAL (output only)", +#ifdef SPLIT_REND_WITH_HEAD_ROT + "BINAURAL_SPLIT_PCM", + "BINAURAL_SPLIT_CODED", +#endif "BINAURAL_ROOM_IR (output only)", "BINAURAL_ROOM_REVERB (output only)", }; @@ -3359,29 +3765,81 @@ static void convertInputBuffer( const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, - float *floatBuffer ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + float *floatBuffer, + const int16_t cldfb_in_flag, + IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna +#else + float *floatBuffer +#endif +) { int16_t chnl, smpl, i; i = 0; - for ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( cldfb_in_flag ) + { + int16_t slotIdx, numCldfbBands, numFloatPcmSamples; + float fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; + + numFloatPcmSamples = numFloatSamplesPerChannel >> 1; + numCldfbBands = numFloatPcmSamples / IVAS_CLDFB_NO_COL_MAX; + + /* CLDFB Analysis*/ + assert( numIntSamplesPerChannel <= IVAS_MAX_OUTPUT_CHANNELS * IVAS_MAX_FRAME_SIZE ); + for ( smpl = 0; smpl < numFloatPcmSamples; ++smpl ) { for ( chnl = 0; chnl < numChannels; ++chnl ) { if ( i < numIntSamplesPerChannel ) { - floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = (float) intBuffer[i]; + fIn[chnl][smpl] = (float) intBuffer[i]; } else { - floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0.f; + fIn[chnl][smpl] = 0.f; } ++i; } } + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + for ( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) + { + IVAS_REND_cldfbAnalysis_ts_wrapper( &fIn[chnl][numCldfbBands * slotIdx], + &floatBuffer[( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], + &floatBuffer[numCldfbBands + ( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], + numCldfbBands, cldfbAna[chnl] ); + } + } + } + else + { +#endif + for ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + if ( i < numIntSamplesPerChannel ) + { + floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = (float) intBuffer[i]; + } + else + { + floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0.f; + } + + ++i; + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif + return; } @@ -3469,36 +3927,97 @@ static void convertOutputBuffer_fx( * Convert output buffer from the renderer (float, packed) to a format ready * for writing to a WAV/PCM file (int16_t, interleaved) *--------------------------------------------------------------------------*/ + static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, - int16_t *intBuffer ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t *intBuffer, + const int16_t cldfb_in_flag, + IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn +#else + int16_t *intBuffer +#endif +) { int16_t chnl, smpl, i; float temp; i = 0; - for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( cldfb_in_flag ) { + int16_t slotIdx, numCldfbBands, numPcmSamples, b; + float fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; + float re[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; + float im[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; + + numPcmSamples = numSamplesPerChannel >> 1; + numCldfbBands = numPcmSamples / IVAS_CLDFB_NO_COL_MAX; + + /* CLDFB Synthesis*/ for ( chnl = 0; chnl < numChannels; ++chnl ) { - temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; - temp = (float) floor( temp + 0.5f ); - if ( temp > IVAS_MAX16B_FLT ) + for ( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) { - temp = IVAS_MAX16B_FLT; + for ( b = 0; b < numCldfbBands; b++ ) + { + re[chnl][slotIdx][b] = floatBuffer[( chnl * numSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands ) + b]; + im[chnl][slotIdx][b] = floatBuffer[numCldfbBands + ( chnl * numSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands ) + b]; + } } - else if ( temp < IVAS_MIN16B_FLT ) + } + + /* Implement CLDFB synthesis */ + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + float *RealBuffer[IVAS_CLDFB_NO_COL_MAX]; + float *ImagBuffer[IVAS_CLDFB_NO_COL_MAX]; + + for ( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) { - temp = IVAS_MIN16B_FLT; + RealBuffer[slotIdx] = re[chnl][slotIdx]; + ImagBuffer[slotIdx] = im[chnl][slotIdx]; } - intBuffer[i] = (int16_t) temp; - ++i; + IVAS_REND_cldfbSynthesis_wrapper( RealBuffer, ImagBuffer, &( fIn[chnl][0] ), numCldfbBands * IVAS_CLDFB_NO_COL_MAX, cldfbSyn[chnl] ); + } + for ( smpl = 0; smpl < numPcmSamples; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + intBuffer[i] = (int16_t) roundf( fIn[chnl][smpl] ); + ++i; + } } } + else + { +#endif + for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + { + for ( chnl = 0; chnl < numChannels; ++chnl ) + { + temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; + temp = (float) floor( temp + 0.5f ); + if ( temp > IVAS_MAX16B_FLT ) + { + temp = IVAS_MAX16B_FLT; + } + else if ( temp < IVAS_MIN16B_FLT ) + { + temp = IVAS_MIN16B_FLT; + } + intBuffer[i] = (int16_t) temp; + + ++i; + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif return; } diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c index 5a3d2e1a2..fe3ed88ea 100644 --- a/lib_com/cldfb.c +++ b/lib_com/cldfb.c @@ -61,7 +61,6 @@ static void cldfb_init_proto_and_twiddles( HANDLE_CLDFB_FILTER_BANK hs ); static void cldfb_init_proto_and_twiddles_enc_fx( HANDLE_CLDFB_FILTER_BANK hs ); - /*-------------------------------------------------------------------* * cplxMult() * diff --git a/lib_com/cnst.h b/lib_com/cnst.h index fe16db670..6cfa7ea41 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -173,6 +173,7 @@ #define MIN16B_FLT_FX_IN_Q15 -1073741824//Q15 #define PCM16_TO_FLT_FAC 32768.0f #define PCM16_TO_FLT_FAC_FX 32768 //Q0 +#define PCM16_TO_FLT_FAC_FX_Q15 1073741824L //16Q15 #define MDFT_NORM_SCALING ( 1.0f / PCM16_TO_FLT_FAC ) #define MDFT_NORM_SCALING_FX 65536 //Q31 #define LOG2_MDFT_NORM_SCALING_FX -503316448 //Q25 @@ -3042,6 +3043,8 @@ enum #define EVS_2PI_FX_Q27 843314856 /* 2 * pi in Q28 */ #define EVS_PI_BY_2_FX (Word16)(0x3244) // Q13 //#define EVS_PI_FX (Word16)(0x6488) +#define EVS_PI_FX16 (Word16)(0x6488) +#define PI2_FX 1686629713 //Q28 #define LG10 24660 /* 10*log10(2) in Q13 */ diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index b98f2e7d1..894b940b7 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -59,6 +59,12 @@ #define IVAS_MAX_PARAM_SPATIAL_SUBFRAMES 4 #define IVAS_ROOM_ABS_COEFF 6 +/* Maximum buffer length (per channel) in samples */ +#define MAX_BUFFER_LENGTH_PER_CHANNEL ( L_FRAME48k ) + +/* Frame size required when rendering to binaural */ +#define BINAURAL_RENDERING_FRAME_SIZE_MS 5 + /*----------------------------------------------------------------------------------* * Common API enum for output audio configurations *----------------------------------------------------------------------------------*/ @@ -210,10 +216,109 @@ typedef struct _IVAS_JBM_TRACE_DATA } IVAS_JBM_TRACE_DATA; +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*----------------------------------------------------------------------------------* + * Split rendering API constants, structures, and enums + *----------------------------------------------------------------------------------*/ + +#define ISAR_MAX_SPLIT_REND_BITRATE 768000 +#define ISAR_MAX_SPLIT_REND_BITS_BUFFER_SIZE_IN_BYTES ( ( ( (int32_t) ISAR_MAX_SPLIT_REND_BITRATE / IVAS_NUM_FRAMES_PER_SEC ) + 7 ) >> 3 ) +#define ISAR_SPLIT_REND_ADDITIONAL_BYTES_TO_READ 1 +#define SPLIT_REND_BITS_BUFF_SIZE ( ISAR_MAX_SPLIT_REND_BITS_BUFFER_SIZE_IN_BYTES + ISAR_SPLIT_REND_ADDITIONAL_BYTES_TO_READ ) + +typedef enum +{ + DEFAULT_AXIS, + YAW, + PITCH, + ROLL, + YAW_PITCH, + YAW_ROLL, + PITCH_ROLL + +} ISAR_SPLIT_REND_ROT_AXIS; + +typedef enum +{ + ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE, + ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB, + +} ISAR_SPLIT_REND_POSE_CORRECTION_MODE; + +typedef enum +{ + ISAR_SPLIT_REND_CODEC_LCLD, + ISAR_SPLIT_REND_CODEC_LC3PLUS, + ISAR_SPLIT_REND_CODEC_DEFAULT, /* Will use LCLD for CLDFB rendering paths and LC3plus for TD rendering paths */ + ISAR_SPLIT_REND_CODEC_NONE + +} ISAR_SPLIT_REND_CODEC; + +typedef enum +{ + ISAR_SPLIT_REND_RENDERER_SELECTION_CREND, + ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV, + ISAR_SPLIT_REND_RENDERER_SELECTION_PARAMBIN, + ISAR_SPLIT_REND_RENDERER_SELECTION_TDREND, + ISAR_SPLIT_REND_RENDERER_SELECTION_DEFAULT, + +} ISAR_SPLIT_REND_RENDERER_SELECTION; + +typedef struct _ISAR_SPLIT_REND_BITS_DATA +{ + uint8_t *bits_buf; + int32_t buf_len; /*size of bits_buf in bytes. This field should be set by allocator of bits_buf*/ + int32_t bits_written; + int32_t bits_read; + int16_t codec_frame_size_ms; + ISAR_SPLIT_REND_CODEC codec; + ISAR_SPLIT_REND_POSE_CORRECTION_MODE pose_correction; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t isar_frame_size_ms; + int16_t lc3plus_highres; +#endif + +} ISAR_SPLIT_REND_BITS_DATA, *ISAR_SPLIT_REND_BITS_HANDLE; + +typedef struct _ISAR_SPLIT_REND_CONFIG +{ + int32_t splitRendBitRate; /*Bit rate for split rendering mode, if "pcm_out" is set then "splitRendBitRate" is used as a limit for MD bitrate */ + int16_t hq_mode; /*High quality 3DOF mode with additional side information. Requires more pre-renditions. */ + int16_t dof; /*flag to specify if pose correction is needed for 1, 2 or 3 degree of freedoms*/ + /*The axis can be set dynamically per frame based on a file input */ + /*possible values: + 1 - (1dof correction. By default YAW correction) + 2 - (2dof correction. By default YAW and PITCH correction) + 3 - (3dof correction. By default YAW, PITCH and ROLL correction) + */ + int16_t codec_delay_ms; /*PLACEHOLDER (currently being ignored) : look ahead delay of the codec that is used to code BIN signal output of pre-renderer*/ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t isar_frame_size_ms; /* ISAR bit stream frame size in milliseconds */ +#endif + int16_t codec_frame_size_ms; /* Codec frame size in milliseconds, only relevant with LC3plus */ + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode; + ISAR_SPLIT_REND_CODEC codec; + ISAR_SPLIT_REND_RENDERER_SELECTION rendererSelection; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t lc3plus_highres; +#endif + +} ISAR_SPLIT_REND_CONFIG_DATA, *ISAR_SPLIT_REND_CONFIG_HANDLE; +#endif + /*----------------------------------------------------------------------------------* * Renderer API structures and enums *----------------------------------------------------------------------------------*/ +#ifdef DEBUGGING +typedef enum +{ + IVAS_RENDER_TYPE_OVERRIDE_NONE, + IVAS_RENDER_TYPE_OVERRIDE_CREND, + IVAS_RENDER_TYPE_OVERRIDE_FASTCONV + +} IVAS_RENDER_TYPE_OVERRIDE; +#endif typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG { @@ -242,10 +347,33 @@ typedef struct _IVAS_ROOM_ACOUSTICS_CONFIG typedef struct _IVAS_RENDER_CONFIG { +#ifdef DEBUGGING + IVAS_RENDER_TYPE_OVERRIDE renderer_type_override; +#endif IVAS_ROOM_ACOUSTICS_CONFIG_DATA roomAcoustics; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_CONFIG_DATA split_rend_config; +#endif float directivity[IVAS_MAX_NUM_OBJECTS * 3]; Word16 directivity_fx[IVAS_MAX_NUM_OBJECTS * 3]; // has the following q-factor pattern: {6, 6, 15, 6, 6, 15, 6, 6, 15, 6, 6, 15} } IVAS_RENDER_CONFIG_DATA, *IVAS_RENDER_CONFIG_HANDLE; +typedef struct +{ + int16_t numSamplesPerChannel; + int16_t numChannels; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t is_cldfb; +#endif +} IVAS_REND_AudioBufferConfig; + +typedef struct +{ + IVAS_REND_AudioBufferConfig config; + Word16 q_factor; + Word16 *pq_fact; + Word32 *data_fx; + // Word16 Q_data; +} IVAS_REND_AudioBuffer; #endif /* COMMON_API_TYPES_H */ diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index 1198008f6..8ec9e112b 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -97,6 +97,12 @@ typedef enum * input data errors * *----------------------------------------*/ IVAS_ERR_INVALID_BITSTREAM = 0x2000, +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM, + IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM_CONFIG, +#endif +#endif /*----------------------------------------* * hardware errors * @@ -135,6 +141,10 @@ typedef enum IVAS_ERR_ACOUSTIC_ENVIRONMENT_MISSING, IVAS_ERR_INVALID_ER_PARAM, IVAS_ERR_DIRECTIVITY_PATTERN_ID_MISSING, +#ifdef SPLIT_REND_WITH_HEAD_ROT + IVAS_ERR_LC3PLUS_INVALID_BITRATE, + IVAS_ERR_INVALID_SPLIT_REND_CONFIG, +#endif /*----------------------------------------* * unknown error * @@ -233,6 +243,12 @@ static inline const char *ivas_error_to_string( ivas_error error_code ) return "Wrong mode"; case IVAS_ERR_HEAD_ROTATION_NOT_SUPPORTED: return "Head rotation not supported"; +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_ERR_LC3PLUS_INVALID_BITRATE: + return "Specified split rendering bit rate is not supported"; + case IVAS_ERR_INVALID_SPLIT_REND_CONFIG: + return "Specified split rendering configuration is invalid"; +#endif case IVAS_ERR_EXT_ORIENTATION_NOT_SUPPORTED: return "External orientation not supported"; case IVAS_ERR_DIRECTIVITY_NOT_SUPPORTED: diff --git a/lib_rend/ivas_limiter.c b/lib_com/ivas_limiter.c similarity index 100% rename from lib_rend/ivas_limiter.c rename to lib_com/ivas_limiter.c diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 03bc3d6e5..e7827023b 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -42,6 +42,7 @@ #include "stat_com.h" #include "ivas_stat_enc.h" #include "ivas_stat_dec.h" +#include "ivas_stat_rend.h" #include "ivas_stat_com.h" #include "ivas_error_utils.h" diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index e7eaea5b7..cd046cb5b 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -42,6 +42,7 @@ #include "stat_com.h" #include "ivas_stat_enc.h" #include "ivas_stat_dec.h" +#include "ivas_stat_rend.h" #include "ivas_stat_com.h" #include "ivas_error_utils.h" @@ -2608,6 +2609,52 @@ Word16 getNumChanAnalysis_fx( Encoder_Struct *st_ivas /* i : IVAS encoder structure */ ); +/*----------------------------------------------------------------------------------* + * Limiter prototypes + *----------------------------------------------------------------------------------*/ + + +ivas_error ivas_limiter_open( + IVAS_LIMITER_HANDLE *hLimiter_out, /* o : limiter struct handle */ + const int16_t num_channels, /* i : number of I/O channels */ + const int32_t sampling_rate /* i : sampling rate for processing */ +); + +void ivas_limiter_close( + IVAS_LIMITER_HANDLE *phLimiter /* i/o: pointer to limiter handle, can be NULL */ +); + +void ivas_limiter_dec( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + float *output[MAX_OUTPUT_CHANNELS], /* i/o: input/output buffer */ + const int16_t num_channels, /* i : number of channels to be processed */ + const int16_t output_frame, /* i : number of samples per channel in the buffer */ + const int16_t BER_detect /* i : BER detect flag */ +); +void ivas_limiter_dec_fx( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + Word32 *output[MAX_OUTPUT_CHANNELS], /* i/o: input/output buffer */ + const Word16 num_channels, /* i : number of channels to be processed */ + const Word16 output_frame, /* i : number of samples per channel in the buffer */ + const Word16 BER_detect, /* i : BER detect flag */ + Word16 q_factor /* i : Q factor of the output samples */ +); +void limiter_process( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + const int16_t output_frame, /* i : number of samples to be processed per channel in the I/O buffer */ + const float threshold, /* i : signal amplitude above which limiting starts to be applied */ + const int16_t BER_detect, /* i : BER detect flag */ + int16_t *strong_saturation_cnt /* i/o: counter of strong saturations (can be NULL) */ +); +void limiter_process_fx( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + const Word16 output_frame, /* i : number of samples to be processed per channel in the I/O buffer */ + const Word32 threshold, /* i : signal amplitude above which limiting starts to be applied */ + const Word16 BER_detect, /* i : BER detect flag */ + Word16 *strong_saturation_cnt, /* i/o: counter of strong saturations (can be NULL) */ + Word16 q_factor /* i : Q factor of output samples */ +); + ivas_error ivas_limiter_open_fx( IVAS_LIMITER_HANDLE *hLimiter_out, /* o : limiter struct handle */ const Word16 max_num_channels, /* i : maximum number of I/O channels to be processed */ @@ -3647,14 +3694,22 @@ ivas_error ivas_allocate_binaural_hrtf_fx( ); void ivas_binRenderer_fx( - BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */ - COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle*/ - const Word16 numTimeSlots, /* i : number of time slots to render */ + BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, +#endif + COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle*/ + const Word16 numTimeSlots, /* i : number of time slots to render */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 Cldfb_RealBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */ + Word32 Cldfb_ImagBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */ +#else Word32 Cldfb_RealBuffer_Binaural_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ Word32 Cldfb_ImagBuffer_Binaural_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ - Word32 RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ - Word32 ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ - Word16 *Q_in /* i : LS signals exp */ +#endif + Word32 RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ + Word32 ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals */ + Word16 *Q_in /* i : LS signals exp */ ); void ivas_binaural_add_LFE_fx( @@ -5855,4 +5910,38 @@ void reset_metadata_spatial_fx( const Word32 core_brate, /* i : core bitrate */ const Word16 nb_bits_metadata /* i : number of meatdata bits */ ); + +void Euler2Quat( + const float yaw, /* i : yaw (x) */ + const float pitch, /* i : pitch (y) */ + const float roll, /* i : roll (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +); +void Euler2Quat_fx( + const Word32 yaw, /* i : yaw (x) Q22 */ + const Word32 pitch, /* i : pitch (y) Q22 */ + const Word32 roll, /* i : roll (z) Q22 */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +); +float deg2rad( + float degrees ); + +Word32 deg2rad_fx( + Word32 degrees ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT +void Quat2EulerDegree( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float *yaw, /* o : yaw */ + float *pitch, /* o : pitch */ + float *roll /* o : roll */ +); +void Quat2EulerDegree_fx( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + Word32 *yaw_fx, /* o : yaw */ + Word32 *pitch_fx, /* o : pitch */ + Word32 *roll_fx /* o : roll */ +); +#endif + #endif diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c new file mode 100644 index 000000000..d50eb4304 --- /dev/null +++ b/lib_com/ivas_rotation_com.c @@ -0,0 +1,270 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include "ivas_cnst.h" +#include +#include +#include "options.h" +#include +#include "cnst.h" +#include "prot.h" +#include "ivas_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" +#include "prot_fx2.h" +#include "basop_mpy.h" +#include "basop_util.h" +#include "enh64.h" +/*------------------------------------------------------------------------- + * Euler2Quat() + * + * Calculate corresponding Quaternion from Euler angles in radians + *------------------------------------------------------------------------*/ +void Euler2Quat_fx( + const Word32 yaw, /* i : yaw (x) Q22 */ + const Word32 pitch, /* i : pitch (y) Q22 */ + const Word32 roll, /* i : roll (z) Q22 */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation Q19 */ +) +{ + Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) ); // Q14 + Word16 sr = getSinWord16( extract_l( L_shr_r( roll, 10 ) ) ); + Word16 cp = getCosWord16( extract_l( L_shr_r( pitch, 10 ) ) ); + Word16 sp = getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ); + Word16 cy = getCosWord16( extract_l( L_shr_r( yaw, 10 ) ) ); + Word16 sy = getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ); + quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); // Q19 + move32(); + quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); // Q19 + move32(); + quat->y_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( sr, cp ), sy ), Mpy_32_16_1( L_mult0( cr, sp ), cy ) ), 5 ); // Q19 + move32(); + quat->z_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( cr, cp ), sy ), Mpy_32_16_1( L_mult0( sr, sp ), cy ) ), 5 ); // Q19 + move32(); + + return; +} +void Euler2Quat( + const float yaw, /* i : yaw (x) */ + const float pitch, /* i : pitch (y) */ + const float roll, /* i : roll (z) */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ +) +{ + float cr = cosf( roll * 0.5f ); + float sr = sinf( roll * 0.5f ); + float cp = cosf( pitch * 0.5f ); + float sp = sinf( pitch * 0.5f ); + float cy = cosf( yaw * 0.5f ); + float sy = sinf( yaw * 0.5f ); + quat->w = cr * cp * cy + sr * sp * sy; + quat->x = sr * cp * cy - cr * sp * sy; + quat->y = sr * cp * sy + cr * sp * cy; + quat->z = cr * cp * sy - sr * sp * cy; + + return; +} + + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*------------------------------------------------------------------------- + * Quat2EulerDegree() + * + * Quaternion handling: calculate corresponding Euler angles in degrees + *------------------------------------------------------------------------*/ +void Quat2EulerDegree_fx( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + Word32 *yaw_fx, /* o : yaw */ + Word32 *pitch_fx, /* o : pitch */ + Word32 *roll_fx /* o : roll */ +) +{ + IF( NE_32( quat.w_fx, L_negate( 12582912 ) /*3.0f in Q22*/ ) ) + { + Word32 tmp1 = W_extract_l( W_shr( W_mult0_32_32( quat.w_fx, quat.x_fx ), Q22 ) ); // Q22 + Word32 tmp2 = W_extract_l( W_shr( W_mult0_32_32( quat.y_fx, quat.z_fx ), Q22 ) ); // Q22 + Word32 tmp3 = L_shl( L_add( tmp1, tmp2 ), 1 ); // Q22 + + Word32 tmp4 = W_extract_l( W_shr( W_mult0_32_32( quat.x_fx, quat.x_fx ), Q22 ) ); // Q22 + Word32 tmp5 = W_extract_l( W_shr( W_mult0_32_32( quat.y_fx, quat.y_fx ), Q22 ) ); // Q22 + Word32 tmp6 = L_shl( L_add( tmp4, tmp5 ), 1 ); + Word32 tmp7 = L_sub( ONE_IN_Q22, tmp6 ); + + IF( tmp3 >= -2 && tmp3 <= 2 ) + { + tmp3 = 0; + } + IF( tmp7 >= -2 && tmp7 <= 2 ) + { + tmp7 = 0; + } + + Word16 yaw_fx_16 = BASOP_util_atan2( tmp3, tmp7, 0 ); // Q13 + *yaw_fx = Mpy_32_16_1( 961263669 /*_180_OVER_PI in Q24*/, yaw_fx_16 ); + + Word32 p_fx; + Word32 tmp8 = W_extract_l( W_shr( W_mult0_32_32( quat.w_fx, quat.y_fx ), Q22 ) ); // Q22 + Word32 tmp9 = W_extract_l( W_shr( W_mult0_32_32( quat.z_fx, quat.x_fx ), Q22 ) ); // Q22 + p_fx = L_shl( L_sub( tmp8, tmp9 ), 1 ); + p_fx = max( L_negate( ONE_IN_Q22 ), min( ONE_IN_Q22, p_fx ) ); // Q22 + + Word32 p_fx_sq = W_extract_l( W_shr( W_mult0_32_32( p_fx, p_fx ), Q22 ) ); + Word16 res_exp = 0; + Word32 one_minus_p_fx_sq = BASOP_Util_Add_Mant32Exp( ONE_IN_Q30, 1, L_negate( p_fx_sq ), 31 - Q22, &res_exp ); + Word32 sqrt_one_minus_p_fx_sq = Sqrt32( one_minus_p_fx_sq, &res_exp ); + + Word16 pitch_fx_16 = BASOP_util_atan2( p_fx, sqrt_one_minus_p_fx_sq, ( 31 - Q22 ) - res_exp ); + + *pitch_fx = Mpy_32_16_1( 961263669 /*_180_OVER_PI in Q24*/, pitch_fx_16 ); + + Word32 tmp10 = W_extract_l( W_shr( W_mult0_32_32( quat.w_fx, quat.z_fx ), Q22 ) ); // Q22 + Word32 tmp11 = W_extract_l( W_shr( W_mult0_32_32( quat.x_fx, quat.y_fx ), Q22 ) ); // Q22 + Word32 tmp12 = L_shl( L_add( tmp10, tmp11 ), 1 ); // Q22 + + Word32 tmp13 = W_extract_l( W_shr( W_mult0_32_32( quat.y_fx, quat.y_fx ), Q22 ) ); // Q22 + Word32 tmp14 = W_extract_l( W_shr( W_mult0_32_32( quat.z_fx, quat.z_fx ), Q22 ) ); // Q22 + Word32 tmp15 = L_shl( L_add( tmp13, tmp14 ), 1 ); // Q22 + Word32 tmp16 = L_sub( ONE_IN_Q22, tmp15 ); // Q22 + + IF( tmp12 >= -2 && tmp12 <= 2 ) + { + tmp12 = 0; + } + IF( tmp16 >= -2 && tmp16 <= 2 ) + { + tmp16 = 0; + } + Word16 roll_fx_16 = BASOP_util_atan2( tmp12, tmp16, 0 ); // Q13 + *roll_fx = Mpy_32_16_1( 961263669 /*_180_OVER_PI in Q24*/, roll_fx_16 ); + } + ELSE + { + /* Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention + * + * yaw: rotate scene counter-clockwise in the horizontal plane + * pitch: rotate scene in the median plane, increase elevation with positive values + * roll: rotate scene from the right ear to the top + */ + *yaw_fx = quat.z_fx; + *pitch_fx = quat.y_fx; + *roll_fx = quat.x_fx; + } + + return; +} + +void Quat2EulerDegree( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float *yaw, /* o : yaw */ + float *pitch, /* o : pitch */ + float *roll /* o : roll */ +) +{ + if ( quat.w != -3.0 ) + { + float p; + + *yaw = atan2f( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) ); + + p = 2 * ( quat.w * quat.y - quat.z * quat.x ); + p = max( -1.0f, min( 1.0f, p ) ); + *pitch = asinf( p ); + + *roll = atan2f( 2 * ( quat.w * quat.z + quat.x * quat.y ), 1 - 2 * ( quat.y * quat.y + quat.z * quat.z ) ); + + *yaw *= _180_OVER_PI; + *pitch *= _180_OVER_PI; + *roll *= _180_OVER_PI; + } + else + { + /* Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention + * + * yaw: rotate scene counter-clockwise in the horizontal plane + * pitch: rotate scene in the median plane, increase elevation with positive values + * roll: rotate scene from the right ear to the top + */ + *yaw = quat.z; + *pitch = quat.y; + *roll = quat.x; + } + + return; +} +#endif + +/*------------------------------------------------------------------------- + * deg2rad() + * + * Converts degrees to normalized radians + *------------------------------------------------------------------------*/ +#define DEGREE_180 ( Word32 )( 180.0 * ONE_IN_Q22 ) +#define DEGREE_360 ( Word32 )( 360.0 * ONE_IN_Q22 ) +#define PI_OVER_180_FX ( Word32 )( ( EVS_PI / 180.0f ) * ONE_IN_Q31 ) +/*------------------------------------------------------------------------- + * deg2rad() + * + * Converts degrees to normalized radians + *------------------------------------------------------------------------*/ +Word32 deg2rad_fx( + Word32 degrees // Q23 +) +{ + WHILE( GE_32( degrees, DEGREE_180 ) ) + { + degrees = L_sub( degrees, DEGREE_360 ); + } + WHILE( LE_32( degrees, -DEGREE_180 ) ) + { + degrees = L_add( degrees, DEGREE_360 ); + } + + return Mpy_32_32( PI_OVER_180_FX, degrees ); // Q23 +} + +} +float deg2rad( + float degrees ) +{ + while ( degrees >= 180.0f ) + { + degrees = degrees - 360.0f; + } + while ( degrees <= -180.0f ) + { + degrees = degrees + 360.0f; + } + + return PI_OVER_180 * degrees; +} diff --git a/lib_com/options.h b/lib_com/options.h index 250116483..515c576f1 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -123,4 +123,10 @@ #define FIX_ISSUE_1187 /* Ittiam: Fix for issue 1187: Assertion error observed in evs_enc_fx (with option stereo_dmx_evs) from bass_pf_enc_fx function*/ #define FIX_ISSUE_1186 /* Ittiam: Fix for Issue 1186: Energy/scaling issue for ISM-1 at all bitrates */ #define FIX_ISSUE_1165 /* Ittiam: Fix for issue 1165: Assertion in lpc2lsp_fx for OMASA LTV input */ + +#define SPLIT_REND_WITH_HEAD_ROT /* Dlb,FhG: Split Rendering contributions 21 and 35 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT +#define SPLIT_REND_POSE_CORRECTION_UNUSED_BITS +#define ISAR_BITSTREAM_UPDATE_LC3PLUS /* FhG: Multiple improvements to the ISAR bitstream when LC3plus is used. See MR 1456 for details. */ +#endif #endif diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 36246f739..bc31e32e8 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -63,7 +63,12 @@ static void ivas_binRenderer_filterModule_fx( Word32 CLDFB_real[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : real part of LS signals Q_curr*/ Word32 CLDFB_imag[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : imag part of LS signals Q_curr*/ const Word16 numTimeSlots, /* i : number of time slots to process */ - BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */ + const Word16 pos_idx, /* i : pose index */ +#else + BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: fastconv binaural renderer handle */ +#endif Word16 Q_curr ) { Word16 bandIdx, k, chIdx, tapIdx; @@ -75,9 +80,15 @@ static void ivas_binRenderer_filterModule_fx( { FOR( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + filterStatesLeftRealPtr_fx = (Word32 *) &( hBinRenderer->hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx][0] ); + filterStatesLeftImagPtr_fx = (Word32 *) &( hBinRenderer->hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx][0] ); + Q_filterStates = (Word16 *) &( hBinRenderer->hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx][chIdx][0] ); +#else filterStatesLeftRealPtr_fx = (Word32 *) &( hBinRenderer->hBinRenConvModule->filterStatesLeftReal_fx[bandIdx][chIdx][0] ); filterStatesLeftImagPtr_fx = (Word32 *) &( hBinRenderer->hBinRenConvModule->filterStatesLeftImag_fx[bandIdx][chIdx][0] ); Q_filterStates = (Word16 *) &( hBinRenderer->hBinRenConvModule->Q_filterStatesLeft[bandIdx][chIdx][0] ); +#endif filterTapsLeftRealPtr_fx = hBinRenderer->hBinRenConvModule->filterTapsLeftReal_fx[bandIdx][chIdx]; // Q29 filterTapsLeftImagPtr_fx = hBinRenderer->hBinRenConvModule->filterTapsLeftImag_fx[bandIdx][chIdx]; // Q29 @@ -180,9 +191,18 @@ static ivas_error ivas_binRenderer_convModuleOpen( const Word16 renderer_type, const Word16 isLoudspeaker, const AUDIO_CONFIG input_config, - const HRTFS_FASTCONV_HANDLE hHrtf ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + const HRTFS_FASTCONV_HANDLE hHrtf, + const Word16 num_poses +#else + const HRTFS_FASTCONV_HANDLE hHrtf +#endif +) { Word16 bandIdx, chIdx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif BINRENDERER_CONV_MODULE_HANDLE_FX hBinRenConvModule; @@ -308,7 +328,77 @@ static ivas_error ivas_binRenderer_convModuleOpen( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( hBinRenConvModule->filterStatesLeftReal_fx = (Word32 ****) malloc( num_poses * sizeof( Word32 *** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag_fx = (Word32 ****) malloc( num_poses * sizeof( Word32 *** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + IF( ( hBinRenConvModule->Q_filterStatesLeft = (Word16 ****) malloc( num_poses * sizeof( Word16 *** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + if ( ( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx] = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx] = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + IF( ( hBinRenConvModule->Q_filterStatesLeft[pos_idx] = (Word16 ***) malloc( hBinRenderer->conv_band * sizeof( Word16 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) + { + if ( ( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx] = (Word32 **) malloc( hBinRenderer->nInChannels * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + IF( ( hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx] = (Word16 **) malloc( hBinRenderer->nInChannels * sizeof( Word16 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) + { + if ( ( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx] = (Word32 *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + if ( ( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx] = (Word32 *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + + IF( ( hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx][chIdx] = (Word16 *) malloc( hBinRenConvModule->numTapsArray[bandIdx] * sizeof( Word16 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); + } + } + } + } +#else IF( ( hBinRenConvModule->filterStatesLeftReal_fx = (Word32 ***) malloc( hBinRenderer->conv_band * sizeof( Word32 ** ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Convolution Module \n" ) ); @@ -359,6 +449,7 @@ static ivas_error ivas_binRenderer_convModuleOpen( } } } +#endif /* set memories */ FOR( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) { diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 95cca12a0..46cb389bf 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -980,6 +980,9 @@ ivas_error ivas_dirac_dec_config_fx( Word16 need_parambin; Word16 dec_param_estim_old; Word16 dec_param_estim_new; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 num_poses, pos_idx; +#endif error = IVAS_ERR_OK; move32(); @@ -1010,6 +1013,16 @@ ivas_error ivas_dirac_dec_config_fx( move16(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + num_poses = 1; + move16(); + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + } +#endif + sparfoa_flag = 0; move16(); test(); @@ -1056,7 +1069,11 @@ ivas_error ivas_dirac_dec_config_fx( IF( !need_parambin ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); +#else ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#endif } need_dirac_rend = 0; @@ -1129,7 +1146,11 @@ ivas_error ivas_dirac_dec_config_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0] == NULL ) +#else IF( st_ivas->hDiracDecBin == NULL ) +#endif { IF( NE_32( ( error = ivas_dirac_dec_init_binaural_data_fx( st_ivas, st_ivas->hHrtfParambin ) ), IVAS_ERR_OK ) ) { @@ -1141,34 +1162,75 @@ ivas_error ivas_dirac_dec_config_fx( /* This is required to keep BE in rate switching. This probably means that 1TC and 2TC MASA perform differently. */ test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0]->h_freq_domain_decorr_ap_params != NULL && !( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->nSCE > 0 ) ) +#else IF( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params != NULL && !( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->nSCE > 0 ) ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_decorr_close_fx( &st_ivas->hDiracDecBin[0]->h_freq_domain_decorr_ap_params, &st_ivas->hDiracDecBin[0]->h_freq_domain_decorr_ap_state ); // done +#else ivas_dirac_dec_decorr_close_fx( &st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params, &st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_state ); // done +#endif } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin[0]->hTdDecorr ), &( st_ivas->hDiracDecBin[0]->useTdDecorr ) ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* copy td-decorr flag to split renderer side rendereres */ + FOR( pos_idx = 1; pos_idx < num_poses; pos_idx++ ) + { + st_ivas->hDiracDecBin[pos_idx]->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; + } + IF( !st_ivas->hDiracDecBin[0]->useTdDecorr ) +#else IF( !st_ivas->hDiracDecBin->useTdDecorr ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0]->h_freq_domain_decorr_ap_params == NULL ) +#else IF( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params == NULL ) +#endif { Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX]; ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, st_ivas->hDecoderConfig->output_Fs, st_ivas->hSpatParamRendCom->num_freq_bands ); - +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( st_ivas->hDiracDecBin[0]->h_freq_domain_decorr_ap_params ), &( st_ivas->hDiracDecBin[0]->h_freq_domain_decorr_ap_state ), st_ivas->hSpatParamRendCom->num_freq_bands, BINAURAL_CHANNELS, BINAURAL_CHANNELS, + DIRAC_SYNTHESIS_PSD_LS, frequency_axis_fx, BINAURAL_CHANNELS, st_ivas->hDecoderConfig->output_Fs ) ), + IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_params ), &( st_ivas->hDiracDecBin->h_freq_domain_decorr_ap_state ), st_ivas->hSpatParamRendCom->num_freq_bands, BINAURAL_CHANNELS, BINAURAL_CHANNELS, DIRAC_SYNTHESIS_PSD_LS, frequency_axis_fx, BINAURAL_CHANNELS, st_ivas->hDecoderConfig->output_Fs ) ), IVAS_ERR_OK ) ) { return error; } +#endif } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + st_ivas->hDiracDecBin[pos_idx]->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + move16(); + } +#else st_ivas->hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); move16(); +#endif } } } @@ -2185,8 +2247,13 @@ void ivas_dirac_dec_render_sf_fx( /*CLDFB: last output channels reserved to LFT for CICPx*/ Word32 Cldfb_RealBuffer_fx[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_fx[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#else Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#endif Word16 index = 0, num_freq_bands = 0; move16(); move16(); @@ -3712,7 +3779,29 @@ void ivas_dirac_dec_render_sf_fx( input_q = Q6; move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( st_ivas->hSplitBinRend->hCldfbDataOut != NULL ) + { + FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + FOR( ch = 0; ch < st_ivas->hBinRenderer->nInChannels; ch++ ) + { + Copy32( Cldfb_RealBuffer_fx[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer_fx[ch][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); + Copy32( Cldfb_ImagBuffer_fx[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer_fx[ch][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); + } + } + st_ivas->hSplitBinRend->hCldfbDataOut->config = st_ivas->hIntSetup.output_config; + move16(); + } + } +#endif + ivas_binRenderer_fx( st_ivas->hBinRenderer, +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, +#endif st_ivas->hCombinedOrientationData, hSpatParamRendCom->subframe_nbslots[subframe_idx], Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, @@ -3721,6 +3810,24 @@ void ivas_dirac_dec_render_sf_fx( Scale_sig32( Cldfb_RealBuffer_Binaural_fx[0][0], i_mult( BINAURAL_CHANNELS, i_mult( MAX_PARAM_SPATIAL_SUBFRAMES, CLDFB_NO_CHANNELS_MAX ) ), sub( Q6, input_q ) ); // Q6 Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[0][0], i_mult( BINAURAL_CHANNELS, i_mult( MAX_PARAM_SPATIAL_SUBFRAMES, CLDFB_NO_CHANNELS_MAX ) ), sub( Q6, input_q ) ); // Q6 +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + Word16 pos_idx; + FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + { + FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[( add( i_mult( pos_idx, BINAURAL_CHANNELS ) ), ch )][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); // Q6 + Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[( add( i_mult( pos_idx, BINAURAL_CHANNELS ) ), ch )][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); // Q6 + } + } + } + } +#endif + /* Inverse CLDFB*/ FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { @@ -3730,10 +3837,17 @@ void ivas_dirac_dec_render_sf_fx( Word32 *ImagBuffer_fx[MAX_PARAM_SPATIAL_SUBFRAMES]; FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe_idx]; i++ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + RealBuffer_fx[i] = Cldfb_RealBuffer_Binaural_fx[0][ch][i]; + move32(); + ImagBuffer_fx[i] = Cldfb_ImagBuffer_Binaural_fx[0][ch][i]; + move32(); +#else RealBuffer_fx[i] = Cldfb_RealBuffer_Binaural_fx[ch][i]; move32(); ImagBuffer_fx[i] = Cldfb_ImagBuffer_Binaural_fx[ch][i]; move32(); +#endif } scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->p_filter_length, sub( ( Q6 - 1 ), st_ivas->cldfbSynDec[ch]->Q_cldfb_state ) ); // Q6-1 diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 35844b5e5..8fe884c3f 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -44,6 +44,11 @@ #include "wmc_auto.h" #include "prot_fx.h" #include "ivas_prot_fx.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "lib_isar_pre_rend.h" +#include "isar_prot.h" +#include "isar_stat.h" +#endif /*-------------------------------------------------------------------* @@ -55,6 +60,215 @@ static ivas_error ivas_read_format( Decoder_Struct *st_ivas, Word16 *num_bits_re static ivas_error doSanityChecks_IVAS( Decoder_Struct *st_ivas ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +static ivas_error ivas_dec_reconfig_split_rend( Decoder_Struct *st_ivas ); + + +/*-------------------------------------------------------------------* + * ivas_dec_reconfig_split_rend() + * + * IVAS decoder split rend reconfig + *-------------------------------------------------------------------*/ + +static ivas_error ivas_dec_reconfig_split_rend( + Decoder_Struct *st_ivas /* i : IVAS decoder structure */ +) +{ + ivas_error error; + Word16 cldfb_in_flag, num_ch, ch, isCldfbNeeded, i, pcm_out_flag; + SPLIT_REND_WRAPPER *hSplitRendWrapper; + + hSplitRendWrapper = &st_ivas->hSplitBinRend->splitrend; + move16(); + pcm_out_flag = ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; + move16(); + cldfb_in_flag = 0; + move16(); + + IF( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + cldfb_in_flag = 1; + move16(); + } + + ISAR_PRE_REND_GetMultiBinPoseData( &st_ivas->hRenderConfig->split_rend_config, &hSplitRendWrapper->multiBinPoseData, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->sr_pose_pred_axis : DEFAULT_AXIS ); + + isCldfbNeeded = 0; + move16(); + + IF( ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) && EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) || + ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) ) + { + cldfb_in_flag = 0; + move16(); + } + + IF( NE_16( st_ivas->renderer_type, RENDERER_DISABLE ) ) + { + IF( EQ_16( cldfb_in_flag, 0 ) ) + { + isCldfbNeeded = 1; + move16(); + } + ELSE IF( EQ_16( st_ivas->hRenderConfig->split_rend_config.codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) && cldfb_in_flag ) + { + isCldfbNeeded = 1; + move16(); + } + ELSE IF( pcm_out_flag && cldfb_in_flag ) + { + isCldfbNeeded = 1; + move16(); + } + } + ELSE IF( st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) + { + isCldfbNeeded = 1; + move16(); + } + + IF( EQ_16( isCldfbNeeded, 1 ) && hSplitRendWrapper->hCldfbHandles == NULL ) + { + IF( ( hSplitRendWrapper->hCldfbHandles = (CLDFB_HANDLES_WRAPPER_HANDLE) malloc( sizeof( CLDFB_HANDLES_WRAPPER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB handles\n" ) ); + } + + num_ch = i_mult( MAX_HEAD_ROT_POSES, BINAURAL_CHANNELS ); + move16(); + FOR( ch = 0; ch < num_ch; ch++ ) + { + hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] = NULL; + move16(); + } + + num_ch = i_mult( hSplitRendWrapper->multiBinPoseData.num_poses, BINAURAL_CHANNELS ); + move16(); + + FOR( ch = 0; ch < num_ch; ch++ ) + { + IF( ( error = openCldfb_ivas_fx( &( hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] ), CLDFB_ANALYSIS, st_ivas->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not open CLDFB handles\n" ) ); + } + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + if ( ( error = openCldfb_ivas_fx( &( hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] ), CLDFB_SYNTHESIS, st_ivas->hDecoderConfig->output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + ELSE IF( EQ_16( isCldfbNeeded, 0 ) && hSplitRendWrapper->hCldfbHandles != NULL ) + { + num_ch = i_mult( MAX_HEAD_ROT_POSES, BINAURAL_CHANNELS ); + move16(); + FOR( ch = 0; ch < num_ch; ch++ ) + { + IF( hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] != NULL ) + { + deleteCldfb_ivas_fx( &hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] ); + hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] = NULL; + move32(); + } + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + IF( hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] != NULL ) + { + deleteCldfb_ivas_fx( &hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] ); + hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] = NULL; + move32(); + } + } + + free( hSplitRendWrapper->hCldfbHandles ); + hSplitRendWrapper->hCldfbHandles = NULL; + move32(); + } + + IF( ( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) && + ( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || NE_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) && + !( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) ) /* td-rend not needed? */ + { + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + IF( st_ivas->hTdRendHandles[i] != NULL ) + { + st_ivas->hTdRendHandles[i]->HrFiltSet_p = NULL; + move32(); + ivas_td_binaural_close( &st_ivas->hTdRendHandles[i] ); + } + } + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_dec_init_split_rend() + * + * IVAS decoder split rend init + *-------------------------------------------------------------------*/ + +static ivas_error ivas_dec_init_split_rend( + Decoder_Struct *st_ivas /* i : IVAS decoder structure */ +) +{ + ivas_error error; + Word16 cldfb_in_flag, pcm_out_flag; + Word16 mixed_td_cldfb_flag; + + pcm_out_flag = ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; + cldfb_in_flag = 0; + move16(); + + IF( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + cldfb_in_flag = 1; + move16(); + } + + ISAR_PRE_REND_GetMultiBinPoseData( &st_ivas->hRenderConfig->split_rend_config, &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, ( st_ivas->hHeadTrackData != NULL ) ? st_ivas->hHeadTrackData->sr_pose_pred_axis : DEFAULT_AXIS ); + + IF( EQ_16( cldfb_in_flag, 1 ) && ( EQ_16( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ) ) + { + IF( ( st_ivas->hSplitBinRend->hCldfbDataOut = (ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for cldfb data out buffer\n" ) ); + } + } + + mixed_td_cldfb_flag = 0; + move16(); + IF( ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) && EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) || + ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) ) + { + mixed_td_cldfb_flag = 1; + move16(); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + error = ISAR_PRE_REND_open( &st_ivas->hSplitBinRend->splitrend, &st_ivas->hRenderConfig->split_rend_config, st_ivas->hDecoderConfig->output_Fs, cldfb_in_flag, pcm_out_flag, st_ivas->hDecoderConfig->render_framesize, mixed_td_cldfb_flag ); + move16(); +#else + error = ISAR_PRE_REND_open( &st_ivas->hSplitBinRend->splitrend, &st_ivas->hRenderConfig->split_rend_config, st_ivas->hDecoderConfig->output_Fs, cldfb_in_flag, pcm_out_flag, (int16_t) st_ivas->hDecoderConfig->render_framesize, mixed_td_cldfb_flag ); + move16(); +#endif + return error; +} +#endif + /*-------------------------------------------------------------------* * ivas_dec_setup() * @@ -524,6 +738,20 @@ ivas_error ivas_dec_setup( } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /*-----------------------------------------------------------------* + * reconfig split rendering as renderer might change after bitrate switching + *-----------------------------------------------------------------*/ + + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + if ( ( error = ivas_dec_reconfig_split_rend( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif + /*----------------------------------------------------------------* * Reset bitstream pointers *----------------------------------------------------------------*/ @@ -958,7 +1186,12 @@ ivas_error ivas_init_decoder_front( *--------------------------------------------------------------------*/ test(); test(); - IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || + ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) && st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) +#endif + ) { IF( NE_32( ( error = ivas_render_config_open( &( st_ivas->hRenderConfig ) ) ), IVAS_ERR_OK ) ) { @@ -1133,6 +1366,20 @@ ivas_error ivas_init_decoder_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /*-----------------------------------------------------------------* + * Initialize binuaral split rendering + *-----------------------------------------------------------------*/ + + IF( st_ivas->hSplitBinRend != NULL && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || + ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) && st_ivas->hDecoderConfig->Opt_non_diegetic_pan && EQ_16( st_ivas->hRenderConfig->split_rend_config.dof, 0 ) ) ) ) + { + IF( ( error = ivas_dec_init_split_rend( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif /*-----------------------------------------------------------------* * Allocate and initialize SCE/CPE and other handles @@ -2071,9 +2318,15 @@ ivas_error ivas_init_decoder_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hDecoderConfig->output_config, + st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs, ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ) ), + IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hDecoderConfig->output_config, st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -2237,6 +2490,9 @@ ivas_error ivas_init_decoder_fx( { IF( st_ivas->hBinRenderer->render_lfe ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#endif { /* Account for filterbank delay */ binauralization_delay_ns = L_add( binauralization_delay_ns, IVAS_FB_DEC_DELAY_NS ); @@ -2586,7 +2842,14 @@ void ivas_initialize_handles_dec( /* rendering handles */ st_ivas->hBinRenderer = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + st_ivas->hDiracDecBin[i] = NULL; + } +#else st_ivas->hDiracDecBin = NULL; +#endif st_ivas->hDirACRend = NULL; st_ivas->hSpatParamRendCom = NULL; st_ivas->hLsSetUpConversion = NULL; @@ -2611,7 +2874,13 @@ void ivas_initialize_handles_dec( st_ivas->hExtOrientationData = NULL; st_ivas->hCombinedOrientationData = NULL; - +#ifdef SPLIT_REND_WITH_HEAD_ROT + st_ivas->hSplitBinRend = NULL; + for ( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + st_ivas->hTdRendHandles[i] = NULL; + } +#endif /* JBM handles */ st_ivas->hTcBuffer = NULL; st_ivas->hJbmMetadata = NULL; @@ -2748,12 +3017,31 @@ void ivas_destroy_dec_fx( /* Fastconv binaural renderer handle */ ivas_binRenderer_close_fx( &st_ivas->hBinRenderer ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* TD binaural renderer handles */ + for ( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + if ( st_ivas->hTdRendHandles[i] != NULL ) + { + st_ivas->hTdRendHandles[i]->HrFiltSet_p = NULL; + ivas_td_binaural_close_fx( &st_ivas->hTdRendHandles[i] ); + } + } +#endif + /* Parametric binaural renderer handle */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); +#else ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#endif /* Crend handle */ - +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ), ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); +#endif /* Reverb handle */ ivas_reverb_close( &st_ivas->hReverb ); @@ -2919,7 +3207,12 @@ void ivas_init_dec_get_num_cldfb_instances( move16(); } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( st_ivas->hDiracDecBin[0]->useTdDecorr ) +#else IF( st_ivas->hDiracDecBin->useTdDecorr ) +#endif { *numCldfbAnalyses = add( *numCldfbAnalyses, 2 ); move16(); @@ -3206,12 +3499,22 @@ static ivas_error doSanityChecks_IVAS( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && NE_16( output_Fs, 48000 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Error: Only 48kHz output sampling rate is supported for split rendering." ); + } +#endif IF( st_ivas->hDecoderConfig->Opt_Headrotation ) { test(); test(); - IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) ) { return IVAS_ERROR( IVAS_ERR_HEAD_ROTATION_NOT_SUPPORTED, "Wrong set-up: Head-rotation not supported in this configuration" ); } diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index a5f7f7b06..6f1ae3de8 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -198,10 +198,18 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( ivas_param_ism_dec_close_fx( &( st_ivas->hParamIsmDec ), &( st_ivas->hSpatParamRendCom ), st_ivas->hDecoderConfig->output_config ); test(); - IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { /* close the parametric binaural renderer */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); +#else ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#endif /* Open the TD Binaural renderer */ test(); IF( st_ivas->hHrtfTD == NULL || st_ivas->hBinRendererTd == NULL ) @@ -234,13 +242,24 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) ) { /* close the parametric binaural renderer */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); +#else ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#endif /* Open Crend Binaural renderer */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs, ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ) ), IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs ) ), IVAS_ERR_OK ) ) { return error; } +#endif st_ivas->binaural_latency_ns = st_ivas->hCrendWrapper->binaural_latency_ns; move32(); @@ -258,7 +277,11 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( } test(); - IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { /* open the parametric binaural renderer */ IF( NE_32( ( error = ivas_dirac_dec_binaural_copy_hrtfs_fx( &st_ivas->hHrtfParambin ) ), IVAS_ERR_OK ) ) @@ -303,7 +326,11 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( } /* close the crend binaural renderer */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ), ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); +#endif } } diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index 9514e5e2a..50d1811f6 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -556,7 +556,11 @@ static ivas_error ivas_param_ism_rendering_init_fx( test(); test(); test(); - IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) ) { /* computation of proto matrix */ ivas_ism_get_proto_matrix_fx( hOutSetup, nchan_transport, hParamIsmRendering->proto_matrix_fx ); @@ -734,7 +738,11 @@ ivas_error ivas_param_ism_dec_open_fx( test(); test(); IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || - EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) ) + EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) ) { /* Initialize efap handle */ IF( NE_32( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth_fx, hOutSetup.ls_elevation_fx, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) ) @@ -757,7 +765,11 @@ ivas_error ivas_param_ism_dec_open_fx( test(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { IF( NE_32( ( error = ivas_dirac_allocate_parameters_fx( hSpatParamRendCom, 1 ) ), IVAS_ERR_OK ) ) { diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index d69fa8525..0f762462c 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -1688,11 +1688,19 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx( test(); /* delay the objects here for all renderers where it is needed */ IF( - EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || - EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || - EQ_16( st_ivas->renderer_type, RENDERER_OSBA_AMBI ) || - EQ_16( st_ivas->renderer_type, RENDERER_OSBA_LS ) || - EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( +#endif + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || + EQ_16( st_ivas->renderer_type, RENDERER_OSBA_AMBI ) || + EQ_16( st_ivas->renderer_type, RENDERER_OSBA_LS ) || + EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + ) && + ( NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#endif + ) { FOR( n = 0; n < st_ivas->nchan_ism; n++ ) { @@ -1872,6 +1880,9 @@ ivas_error ivas_jbm_dec_render_fx( const Word16 output_q_factor = Q11; move16(); SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 nchan_out_syn_output; +#endif push_wmops( "ivas_dec_render" ); /*----------------------------------------------------------------* @@ -2064,6 +2075,26 @@ ivas_error ivas_jbm_dec_render_fx( #endif } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* Binaural rendering */ + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) + { + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural_fx( st_ivas, p_output_fx, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } +#else /* Binaural rendering */ IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) { @@ -2072,6 +2103,7 @@ ivas_error ivas_jbm_dec_render_fx( return error; } } +#endif ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) { st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; @@ -2090,10 +2122,19 @@ ivas_error ivas_jbm_dec_render_fx( { scale_sig32( p_output_fx[i], *nSamplesRendered, negate( sub( 11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q11 } + +#if defined SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs ) ), IVAS_ERR_OK ) ) { return error; } +#endif + FOR( i = 0; i < nchan_out; i++ ) { scale_sig32( p_output_fx[i], *nSamplesRendered, sub( 11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 @@ -2314,14 +2355,40 @@ ivas_error ivas_jbm_dec_render_fx( scale_sig32( p_tc_fx[i], *nSamplesRendered, negate( sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q11 } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + if ( ( error = ivas_rend_crendProcessSubframesSplitBin( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, + &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, crendInPlaceRotation ? p_output_fx : p_tc_fx, p_output_fx, *nSamplesRendered, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { +#endif + +#if defined SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, + &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, crendInPlaceRotation ? p_output_fx : p_tc_fx, p_output_fx, *nSamplesRendered, output_Fs, 0 ) ), + IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, crendInPlaceRotation ? p_output_fx : p_tc_fx, p_output_fx, *nSamplesRendered, output_Fs ) ), IVAS_ERR_OK ) ) { return error; } +#endif - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif FOR( i = 0; i < nchan_in; i++ ) { @@ -2345,12 +2412,26 @@ ivas_error ivas_jbm_dec_render_fx( } ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - return error; + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_splitBinaural_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } } + else + { +#endif + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif } } ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) @@ -2362,7 +2443,13 @@ ivas_error ivas_jbm_dec_render_fx( /* Rendering */ IF( ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) && !st_ivas->hDecoderConfig->Opt_Headrotation ) { - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_output_fx, p_output_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + /*handled in CLDFB domain already*/ + IF( NE_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#endif + { + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_output_fx, p_output_fx ); + } } ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) { @@ -2578,6 +2665,20 @@ ivas_error ivas_jbm_dec_render_fx( move16(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + nchan_out_syn_output = i_mult( BINAURAL_CHANNELS, st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); + move16(); + } + ELSE + { + nchan_out_syn_output = nchan_out; + move16(); + } + + IF( st_ivas->hDecoderConfig->Opt_Limiter ) +#endif { IF( NE_32( st_ivas->ivas_format, MONO_FORMAT ) ) { @@ -2587,7 +2688,11 @@ ivas_error ivas_jbm_dec_render_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_syn_output_fx( p_output_fx, output_q_factor, *nSamplesRendered, nchan_out_syn_output, data ); +#else ivas_syn_output_fx( p_output_fx, output_q_factor, *nSamplesRendered, nchan_out, data ); +#endif *nSamplesAvailableNext = st_ivas->hTcBuffer->n_samples_available; move16(); @@ -2713,12 +2818,21 @@ ivas_error ivas_jbm_dec_flush_renderer_fx( st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; *st_ivas->hCrendWrapper->p_io_qfactor = 11; move16(); +#if defined SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, + NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ), + IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs ) ), IVAS_ERR_OK ) ) { return error; } +#endif } } ELSE @@ -2745,12 +2859,22 @@ ivas_error ivas_jbm_dec_flush_renderer_fx( } *st_ivas->hCrendWrapper->p_io_qfactor = 11; move16(); + +#if defined SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, + hIntSetupOld, st_ivas->hEFAPdata, st_ivas->hTcBuffer, hTcBuffer->tc_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ), + IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, hIntSetupOld, st_ivas->hEFAPdata, st_ivas->hTcBuffer, hTcBuffer->tc_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs ) ), IVAS_ERR_OK ) ) { return error; } +#endif ivas_binaural_add_LFE_fx( st_ivas, hTcBuffer->n_samples_granularity, st_ivas->hTcBuffer->tc_fx, p_output_fx ); } @@ -2866,6 +2990,9 @@ ivas_error ivas_jbm_dec_flush_renderer_fx( *nSamplesRendered = n_samples_to_render; move16(); /* Only write out the valid data*/ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDecoderConfig->Opt_Limiter ) +#endif { IF( NE_16( st_ivas->ivas_format, MONO_FORMAT ) ) { diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 983eb3309..e87d5da00 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1581,6 +1581,9 @@ ivas_error ivas_masa_dec_reconfigure_fx( Word16 numCldfbAnalyses_old, numCldfbSyntheses_old; ivas_error error; Word32 ism_total_brate; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif error = IVAS_ERR_OK; move16(); @@ -1611,8 +1614,13 @@ ivas_error ivas_masa_dec_reconfigure_fx( test(); test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend == NULL ) || + ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] == NULL ) ) +#else IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend == NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin == NULL ) ) +#endif { /* init a new DirAC dec */ if ( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_OPEN ) ) != IVAS_ERR_OK ) @@ -1625,7 +1633,11 @@ ivas_error ivas_masa_dec_reconfigure_fx( IF( st_ivas->hDirAC != NULL ) { /* close all unnecessary parametric decoding and rendering */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); +#else ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#endif ivas_dirac_rend_close_fx( &( st_ivas->hDirACRend ) ); ivas_spat_hSpatParamRendCom_close_fx( &( st_ivas->hSpatParamRendCom ) ); ivas_dirac_dec_close_fx( &( st_ivas->hDirAC ) ); @@ -1676,7 +1688,11 @@ ivas_error ivas_masa_dec_reconfigure_fx( test(); test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] != NULL ) +#else IF( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin != NULL ) +#endif { if ( NE_32( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ), IVAS_ERR_OK ) ) { @@ -1732,7 +1748,11 @@ ivas_error ivas_masa_dec_reconfigure_fx( test(); test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend != NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] != NULL ) ) +#else IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend != NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin != NULL ) ) +#endif { if ( NE_32( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ), IVAS_ERR_OK ) ) { @@ -1750,7 +1770,11 @@ ivas_error ivas_masa_dec_reconfigure_fx( test(); test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend != NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin[0] != NULL ) ) +#else IF( ( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) && st_ivas->hDirACRend != NULL ) || ( ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) && st_ivas->hDiracDecBin != NULL ) ) +#endif { if ( ( error = ivas_dirac_dec_config_fx( st_ivas, DIRAC_RECONFIGURE ) ) != IVAS_ERR_OK ) { @@ -1760,12 +1784,24 @@ ivas_error ivas_masa_dec_reconfigure_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + IF( st_ivas->hDiracDecBin[pos_idx] != NULL ) + { + /* regularization factor is bitrate-dependent */ + st_ivas->hDiracDecBin[pos_idx]->reqularizationFactor = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + move16(); + } + } +#else IF( st_ivas->hDiracDecBin != NULL ) { /* regularization factor is bitrate-dependent */ st_ivas->hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); move16(); } +#endif test(); IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && EQ_32( st_ivas->last_ivas_format, MASA_FORMAT ) ) /* note: switching within OMASA is handled in ivas_omasa_dec_config() */ @@ -1773,9 +1809,17 @@ ivas_error ivas_masa_dec_reconfigure_fx( /*-----------------------------------------------------------------* * TD Decorrelator *-----------------------------------------------------------------*/ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0] != NULL ) +#else IF( st_ivas->hDiracDecBin != NULL ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin[0]->hTdDecorr ), &( st_ivas->hDiracDecBin[0]->useTdDecorr ) ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -2012,7 +2056,11 @@ void ivas_spar_param_to_masa_param_mapping_fx( move16(); hSpatParamRendCom->numSimultaneousDirections = 1; move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + hDiffuseDist = st_ivas->hDiracDecBin[0]->hDiffuseDist; +#else hDiffuseDist = st_ivas->hDiracDecBin->hDiffuseDist; +#endif nchan_transport = st_ivas->nchan_transport; move16(); band_grouping = hDirAC->band_grouping; diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 4175d15de..7e96c0717 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -1844,8 +1844,13 @@ void ivas_param_mc_dec_render_fx( /*CLDFB*/ Word32 Cldfb_RealBuffer_fx[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_fx[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; +#else Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#endif Word32 *p_output_f_fx[MAX_OUTPUT_CHANNELS]; FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) { @@ -2179,8 +2184,31 @@ void ivas_param_mc_dec_render_fx( { Word16 input_q = 6; move16(); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( st_ivas->hSplitBinRend->hCldfbDataOut != NULL ) + { + FOR( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + FOR( ch = 0; ch < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); ch++ ) + { + Copy32( Cldfb_RealBuffer_fx[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer_fx[ch][add( slot_idx_start, slot_idx )], hParamMC->num_freq_bands ); + Copy32( Cldfb_ImagBuffer_fx[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer_fx[ch][add( slot_idx_start, slot_idx )], hParamMC->num_freq_bands ); + } + } + st_ivas->hSplitBinRend->hCldfbDataOut->config = st_ivas->hIntSetup.output_config; + move16(); + } + } +#endif + /* Implement binaural rendering */ ivas_binRenderer_fx( st_ivas->hBinRenderer, +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, +#endif st_ivas->hCombinedOrientationData, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, @@ -2207,6 +2235,25 @@ void ivas_param_mc_dec_render_fx( Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( Q6, input_q ) ); // Q6 } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + int16_t pos_idx; + FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + { + FOR( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++ ) + { + FOR( ch = 0; ch < nchan_out_cldfb; ch++ ) + { + Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_idx_start, slot_idx )], hParamMC->num_freq_bands ); + Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_idx_start, slot_idx )], hParamMC->num_freq_bands ); + } + } + } + } +#endif + /* update combined orientation access index */ ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); } @@ -2230,8 +2277,13 @@ void ivas_param_mc_dec_render_fx( { IF( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + RealBuffer_fx[i] = Cldfb_RealBuffer_Binaural_fx[0][ch][i]; // Q6 + ImagBuffer_fx[i] = Cldfb_ImagBuffer_Binaural_fx[0][ch][i]; // Q6 +#else RealBuffer_fx[i] = Cldfb_RealBuffer_Binaural_fx[ch][i]; // Q6 ImagBuffer_fx[i] = Cldfb_ImagBuffer_Binaural_fx[ch][i]; // Q6 +#endif } ELSE { diff --git a/lib_dec/ivas_mc_paramupmix_dec.c b/lib_dec/ivas_mc_paramupmix_dec.c index c1bf455a5..f998b0d1b 100644 --- a/lib_dec/ivas_mc_paramupmix_dec.c +++ b/lib_dec/ivas_mc_paramupmix_dec.c @@ -723,13 +723,24 @@ static void ivas_mc_paramupmix_dec_sf( Word32 Cldfb_RealBuffer_subfr_fx[MAX_INTERN_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_subfr_fx[MAX_INTERN_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; #endif // MSAN_FIX + +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + int16_t slot_index_start; +#else Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#endif hMCParamUpmix = st_ivas->hMCParamUpmix; assert( hMCParamUpmix ); push_wmops( "ivas_mc_paramupmix_dec_sf" ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + slot_index_start = st_ivas->hTcBuffer->slots_rendered; +#endif + FOR( i = 0; i < MC_PARAMUPMIX_COMBINATIONS; i++ ) { pPcm_temp_fx[2 * i] = output_fx[i + 4]; /* un-decorrelated Q11*/ @@ -844,14 +855,40 @@ static void ivas_mc_paramupmix_dec_sf( Word16 input_q = 6; move16(); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + /*LFE handling for split rendering cases*/ + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( st_ivas->hSplitBinRend->hCldfbDataOut != NULL ) + { + FOR( slot_idx = 0; slot_idx < st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->subframes_rendered]; slot_idx++ ) + { + FOR( ch = 0; ch < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); ch++ ) + { + Copy32( Cldfb_RealBuffer_subfr[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer[ch][add( slot_index_start, slot_idx )], maxBand ); + Copy32( Cldfb_ImagBuffer_subfr[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer[ch][add( slot_index_start, slot_idx )], maxBand ); + } + } + + st_ivas->hSplitBinRend->hCldfbDataOut->config = st_ivas->hIntSetup.output_config; + move16(); + } + } +#endif + /* Implement binaural rendering */ ivas_binRenderer_fx( st_ivas->hBinRenderer, +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, +#endif st_ivas->hCombinedOrientationData, st_ivas->hTcBuffer->subframe_nbslots[subframeIdx], Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, Cldfb_RealBuffer_subfr_fx, Cldfb_ImagBuffer_subfr_fx, &input_q ); + FOR( Word16 idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) { FOR( Word16 idx2 = 0; idx2 < MAX_PARAM_SPATIAL_SUBFRAMES; idx2++ ) @@ -860,6 +897,25 @@ static void ivas_mc_paramupmix_dec_sf( Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( 6, input_q ) ); // Q6 } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + int16_t pos_idx; + FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + { + FOR( slot_idx = 0; slot_idx < st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; slot_idx++ ) + { + FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) + { + Copy32( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); + Copy32( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); + } + } + } + } +#endif + /* Implement CLDFB synthesis */ FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { @@ -868,8 +924,13 @@ static void ivas_mc_paramupmix_dec_sf( FOR( slot_idx = 0; slot_idx < st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; slot_idx++ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + RealBuffer_fx[slot_idx] = Cldfb_RealBuffer_Binaural_fx[0][ch][slot_idx]; // Q6 + ImagBuffer_fx[slot_idx] = Cldfb_ImagBuffer_Binaural_fx[0][ch][slot_idx]; // Q6 +#else RealBuffer_fx[slot_idx] = Cldfb_RealBuffer_Binaural_fx[ch][slot_idx]; // Q6 ImagBuffer_fx[slot_idx] = Cldfb_ImagBuffer_Binaural_fx[ch][slot_idx]; // Q6 +#endif } scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, Q5 - Q11 ); // Q11 -> Q5 st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q5; diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index f3afead8f..8e34d6642 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -1455,7 +1455,11 @@ static ivas_error ivas_mc_dec_reconfig_fx( test(); test(); test(); - IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { /* remove unneeded binaural renderers */ test(); @@ -1470,10 +1474,17 @@ static ivas_error ivas_mc_dec_reconfig_fx( test(); test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( st_ivas->hCrendWrapper != NULL ) && ( st_ivas->hCrendWrapper->hCrend[0] != NULL ) && ( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) && ( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) || NE_16( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) ) +#else IF( ( st_ivas->hCrendWrapper != NULL ) && ( st_ivas->hCrendWrapper->hCrend != NULL ) && ( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) && ( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) || NE_16( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) ) +#endif { - +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ), ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &( st_ivas->hCrendWrapper ) ); +#endif } test(); @@ -1486,13 +1497,21 @@ static ivas_error ivas_mc_dec_reconfig_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0] != NULL ) +#else IF( st_ivas->hDiracDecBin != NULL ) +#endif { test(); test(); IF( NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && NE_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) && NE_16( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_close_binaural_data( st_ivas->hDiracDecBin ); +#else ivas_dirac_dec_close_binaural_data( &st_ivas->hDiracDecBin ); +#endif } } @@ -1517,22 +1536,39 @@ static ivas_error ivas_mc_dec_reconfig_fx( } IF( EQ_16( st_ivas->hIntSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( error = ivas_rend_initCrendWrapper( &st_ivas->hCrendWrapper, 1 ) ) != IVAS_ERR_OK ) +#else IF( ( error = ivas_rend_initCrendWrapper( &st_ivas->hCrendWrapper ) ) != IVAS_ERR_OK ) +#endif { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend Wrapper\n" ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + st_ivas->hCrendWrapper->hCrend[0] = NULL; + st_ivas->hCrendWrapper->hHrtfCrend = NULL; + IF( ( st_ivas->hCrendWrapper->hCrend[0] = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend\n" ); + } +#else st_ivas->hCrendWrapper->hCrend = NULL; st_ivas->hCrendWrapper->hHrtfCrend = NULL; IF( ( st_ivas->hCrendWrapper->hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend\n" ); } +#endif } } ELSE IF( st_ivas->hCrendWrapper == NULL && ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hDecoderConfig->output_config, st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs, ( st_ivas->hSplitBinRend == NULL ) ? 1 : st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ) ) != IVAS_ERR_OK ) +#else IF( ( error = ivas_rend_openCrend( &( st_ivas->hCrendWrapper ), st_ivas->intern_config, st_ivas->hDecoderConfig->output_config, st_ivas->hRenderConfig, st_ivas->hSetOfHRTF, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 256ce8f96..12ed81e07 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -342,3 +342,158 @@ ivas_error ivas_td_binaural_renderer_sf_fx( return IVAS_ERR_OK; } + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*---------------------------------------------------------------------* + * ivas_td_binaural_renderer_sf_splitBinaural() + * + * Render to multiple binaural pairs based on relative head positions for split rendering. + *---------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_renderer_sf_splitBinaural( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *output[], /* i/o: SCE channels / Binaural synthesis */ + const Word16 nSamplesRendered /* i : number of samples to render */ +) +{ + Word16 i; + Word16 pos_idx; + IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + BINAURAL_TD_OBJECT_RENDERER_HANDLE origTdRendHandle; + ivas_error error; + Word16 original_subframes_rendered; + Word16 original_slots_rendered; + Word32 *p_bin_output[BINAURAL_CHANNELS]; + Word32 output_local[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + + Word16 SrcInd[MAX_NUM_TDREND_CHANNELS]; + + pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData; + move32(); + + /* If not yet allocated, open additional instances of TD renderer */ + FOR( i = 0; i < pMultiBinPoseData->num_poses - 1; ++i ) + { + IF( st_ivas->hTdRendHandles[i] != NULL ) + { + continue; + } + + IF( ( error = ivas_td_binaural_open_unwrap_fx( &st_ivas->hHrtfTD, + st_ivas->hDecoderConfig->output_Fs, + st_ivas->nchan_transport, + st_ivas->ivas_format, + st_ivas->transport_config, + st_ivas->hRenderConfig->directivity_fx, + st_ivas->hTransSetup, + &st_ivas->hTdRendHandles[i], + &st_ivas->binaural_latency_ns, + SrcInd ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* Save current head positions */ + FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) + { + originalHeadRot[i] = st_ivas->hCombinedOrientationData->Quaternions[i]; + } + + original_subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; + move16(); + original_slots_rendered = st_ivas->hTcBuffer->slots_rendered; + move16(); + origTdRendHandle = st_ivas->hBinRendererTd; + move32(); + + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + /* Update head positions */ + IF( NE_16( pos_idx, 0 ) ) + { + FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) + { + IF( EQ_32( originalHeadRot[i].w_fx, -1610612736 /* -3.0f in Q29 */ ) ) + { + assert( 0 ); + } + else + { + st_ivas->hCombinedOrientationData->Quaternions[i].w = -12582912; // Q22 + move32(); + + Quat2EulerDegree( originalHeadRot[i], /* TODO tmu : fix bug with ordering*/ + &st_ivas->hCombinedOrientationData->Quaternions[i].z_fx, + &st_ivas->hCombinedOrientationData->Quaternions[i].y_fx, + &st_ivas->hCombinedOrientationData->Quaternions[i].x_fx ); + + st_ivas->hCombinedOrientationData->Quaternions[i].x_fx = L_add( st_ivas->hCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses[pos_idx][0] ); + st_ivas->hCombinedOrientationData->Quaternions[i].y_fx = L_add( st_ivas->hCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses[pos_idx][1] ); + st_ivas->hCombinedOrientationData->Quaternions[i].z_fx = L_add( st_ivas->hCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses[pos_idx][2] ); + move32(); + move32(); + move32(); + + Euler2Quat_fx( deg2rad_fx( st_ivas->hCombinedOrientationData->Quaternions[i].x_fx ), deg2rad_fx( st_ivas->hCombinedOrientationData->Quaternions[i].y_fx ), deg2rad_fx( st_ivas->hCombinedOrientationData->Quaternions[i].z_fx ), &st_ivas->hCombinedOrientationData->Quaternions[i] ); + } + } + } + + /* set output channels */ + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + p_bin_output[i] = output_local[add( i_mult( pos_idx, BINAURAL_CHANNELS ), i )]; + move32(); + } + st_ivas->hTcBuffer->subframes_rendered = original_subframes_rendered; + move16(); + st_ivas->hTcBuffer->slots_rendered = original_slots_rendered; + move16(); + + /* update combined orientation access index */ + ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); + + /* Render */ + IF( NE_16( pos_idx, 0 ) ) + { + st_ivas->hBinRendererTd = st_ivas->hTdRendHandles[sub( pos_idx, 1 )]; + move32(); + } + + IF( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_bin_output, nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) + { + Word32 *p_tc[MAX_TRANSPORT_CHANNELS]; + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + p_tc[i] = st_ivas->hTcBuffer->tc[i] + st_ivas->hTcBuffer->n_samples_rendered; + } + ivas_binaural_add_LFE_fx( st_ivas, nSamplesRendered, p_tc, p_bin_output ); + } + } + + FOR( i = 0; i < i_mult( pMultiBinPoseData->num_poses, BINAURAL_CHANNELS ); i++ ) + { + Copy32( output_local[i], output[i], nSamplesRendered ); + } + + /* Restore original head rotation */ + FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) + { + st_ivas->hCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; + move32(); + } + + /* restore original td renderer handle */ + st_ivas->hBinRendererTd = origTdRendHandle; + move32(); + + return IVAS_ERR_OK; +} +#endif \ No newline at end of file diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index 509217616..b4f757025 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -422,10 +422,17 @@ ivas_error ivas_omasa_dec_config_fx( * TD Decorrelator *-----------------------------------------------------------------*/ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0] != NULL ) +#else IF( st_ivas->hDiracDecBin != NULL ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin[0]->hTdDecorr ), &( st_ivas->hDiracDecBin[0]->useTdDecorr ) ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) ) - +#endif { return error; } @@ -761,6 +768,12 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( Word32 *p_sepobj_fx[MAX_NUM_OBJECTS]; // Q11 Word32 data_separated_objects_fx[MAX_NUM_OBJECTS][L_FRAME48k]; move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 slot_idx_start; + + slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered; + move16(); +#endif FOR( n = 0; n < MAX_NUM_OBJECTS; n++ ) { @@ -788,15 +801,64 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( /* reset combined orientation access index before calling the td renderer */ ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - return error; - } + Word16 slot_idx, num_cldfb_bands, nchan_transport_orig, cldfb_slots; + Word32 Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX]; + Word32 *p_rend_obj[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* [8 * 2] */ + Word16 q_cldfb = 11; + move16(); - FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) + FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); n++ ) + { + p_rend_obj[n] = &output_f[n][0]; + move32(); + } + + num_cldfb_bands = st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[0]->no_channels; + move16(); + nchan_transport_orig = st_ivas->nchan_transport; + move16(); + st_ivas->nchan_transport = st_ivas->nchan_ism; + move16(); + + IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_rend_obj, *nSamplesRendered ) ) != IVAS_ERR_OK ) /* objects are read from st_ivas->hTcBuffer->tc[2..(1+n_isms)] */ + { + return error; + } + st_ivas->nchan_transport = nchan_transport_orig; + move16(); + cldfb_slots = *nSamplesRendered / num_cldfb_bands; + + FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); ++n ) + { + FOR( slot_idx = 0; slot_idx < cldfb_slots; slot_idx++ ) + { + cldfbAnalysis_ts_fx_fixed_q( &( p_rend_obj[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb ); + + /* note: this intentionally differs from OSBA by: no scaling by 0.5 */ + v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_RealBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands ); + v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_ImagBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands ); + } + } + } + else { - v_add_fx( output_fx[n], p_sepobj_fx[n], output_fx[n], *nSamplesRendered ); +#endif + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } + + FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) + { + v_add_fx( output_fx[n], p_sepobj_fx[n], output_fx[n], *nSamplesRendered ); + } +#ifdef SPLIT_REND_WITH_HEAD_ROT } +#endif return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index f9d14c995..b71b73a6a 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -140,6 +140,12 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( Word32 output_separated_objects_fx[BINAURAL_CHANNELS][L_FRAME48k]; // VE2SB: TBV Word32 *p_sepobj_fx[BINAURAL_CHANNELS]; Word16 channel_offset; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 slot_idx_start; + + slot_idx_start = st_ivas->hSpatParamRendCom->slots_rendered; + move16(); +#endif FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) { @@ -154,20 +160,71 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( return error; } - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - return error; - } + Word16 slot_idx, num_cldfb_bands, b, nchan_transport_orig; + Word16 cldfb_slots; + Word32 Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX]; + Word16 q_cldfb = 11; + move16(); + + num_cldfb_bands = st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[0]->no_channels; + move16(); + nchan_transport_orig = st_ivas->nchan_transport; + move16(); + st_ivas->nchan_transport = st_ivas->nchan_ism; + move16(); + IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, output_f, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + st_ivas->nchan_transport = nchan_transport_orig; + move16(); + cldfb_slots = *nSamplesRendered / num_cldfb_bands; - FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) + FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); ++n ) + { + FOR( slot_idx = 0; slot_idx < cldfb_slots; slot_idx++ ) + { + cldfbAnalysis_ts_fx_fixed_q( &( output_f[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb ); + + FOR( b = 0; b < num_cldfb_bands; b++ ) + { + st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][slot_idx_start + slot_idx][b] = + L_add( L_shr( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][add( slot_idx_start, slot_idx )][b], 1 ), + L_shr( Cldfb_RealBuffer[b], 1 ) ); + move32(); + + st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][slot_idx_start + slot_idx][b] = + L_add( L_shr( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][add(slot_idx_start, slot_idx)][b], 1 ), + L_shrCldfb_ImagBuffer[b], 1) ); + move32(); + } + } + } + } + else { - Word16 i; - FOR( i = 0; i < nSamplesAsked; i++ ) +#endif + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_sepobj_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } + + FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) { - output_fx[n][i] = L_add( L_shr( output_fx[channel_offset + n][i], 1 ), L_shr( p_sepobj_fx[n][i], 1 ) ); - move32(); + Word16 i; + FOR( i = 0; i < nSamplesAsked; i++ ) + { + output_fx[n][i] = L_add( L_shr( output_fx[channel_offset + n][i], 1 ), L_shr( p_sepobj_fx[n][i], 1 ) ); + move32(); + } } +#ifdef SPLIT_REND_WITH_HEAD_ROT } +#endif return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index 64995d8a0..d2aad8218 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -81,7 +81,11 @@ void ivas_renderer_select( test(); test(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { test(); test(); @@ -92,7 +96,11 @@ void ivas_renderer_select( { IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) { - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { *renderer_type = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -106,7 +114,11 @@ void ivas_renderer_select( ELSE /* ISM_MODE_DISC */ { test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { *renderer_type = RENDERER_BINAURAL_OBJECTS_TD; move16(); @@ -127,7 +139,11 @@ void ivas_renderer_select( *internal_config = output_config; move16(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { *renderer_type = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -144,7 +160,11 @@ void ivas_renderer_select( move16(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { *renderer_type = RENDERER_BINAURAL_FASTCONV; move16(); @@ -199,7 +219,11 @@ void ivas_renderer_select( *internal_config = output_config; move16(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { *renderer_type = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -215,7 +239,11 @@ void ivas_renderer_select( *internal_config = transport_config; move16(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { test(); test(); diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index e27bc0638..f1ac7fa76 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -185,7 +185,11 @@ ivas_error ivas_sba_dec_reconfigure_fx( test(); test(); test(); - IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) + IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) ) { RENDERER_TYPE renderer_type_new; Word16 sba_order_internal; @@ -196,7 +200,11 @@ ivas_error ivas_sba_dec_reconfigure_fx( /* copy the logic from ivas_renderer_select(), because calling this function has too many side effects that would affect the flushing */ IF( LE_16( ivas_get_sba_num_TCs_fx( ivas_total_brate, sba_order_internal ), 2 ) ) { - IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { renderer_type_new = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -210,7 +218,11 @@ ivas_error ivas_sba_dec_reconfigure_fx( ELSE { test(); - IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { renderer_type_new = RENDERER_BINAURAL_FASTCONV; move16(); @@ -628,6 +640,15 @@ ivas_error ivas_sba_dec_reconfigure_fx( * TD Decorrelator *-----------------------------------------------------------------*/ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0] != NULL ) + { + IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin[0]->hTdDecorr ), &( st_ivas->hDiracDecBin[0]->useTdDecorr ) ) ), IVAS_ERR_OK ) ) + { + return error; + } + } +#else IF( st_ivas->hDiracDecBin != NULL ) { IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( st_ivas->hDiracDecBin->hTdDecorr ), &( st_ivas->hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) ) @@ -635,6 +656,7 @@ ivas_error ivas_sba_dec_reconfigure_fx( return error; } } +#endif /*-----------------------------------------------------------------* * CLDFB instances @@ -784,7 +806,11 @@ void ivas_sba_dec_digest_tc_fx( ivas_spar_dec_digest_tc_fx( st_ivas, st_ivas->nchan_transport, nCldfbSlots, nSamplesForRendering ); } test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0] != NULL && st_ivas->hDiracDecBin[0]->useTdDecorr ) +#else IF( st_ivas->hDiracDecBin != NULL && ( st_ivas->hDiracDecBin->useTdDecorr ) ) +#endif { Word16 nSamplesLeftForTD, default_frame; Word32 *decorr_signal[BINAURAL_CHANNELS]; @@ -807,9 +833,17 @@ void ivas_sba_dec_digest_tc_fx( { Word16 nSamplesToDecorr = s_min( nSamplesLeftForTD, default_frame ); /*Q0*/ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0]->hTdDecorr ) +#else IF( st_ivas->hDiracDecBin->hTdDecorr ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_td_decorr_process_fx( st_ivas->hDiracDecBin[0]->hTdDecorr, p_tc, decorr_signal, nSamplesToDecorr ); +#else ivas_td_decorr_process_fx( st_ivas->hDiracDecBin->hTdDecorr, p_tc, decorr_signal, nSamplesToDecorr ); +#endif } FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index fdace42d8..628a32c2b 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -1999,7 +1999,11 @@ void ivas_spar_dec_upmixer_sf_fx( test(); test(); test(); - IF( ( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || !( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) && + IF( ( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || !( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) ) && !( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) ) { Scale_sig32( st_ivas->cldfbSynDec[idx_in]->cldfb_state_fx, st_ivas->cldfbSynDec[idx_in]->p_filter_length, -6 ); /*st_ivas->cldfbSynDec[idx_in]->Q_cldfb_state-6*/ diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index cf01ce54f..2d71508f7 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -40,6 +40,7 @@ #include "stat_dec.h" #include "ivas_stat_com.h" #include "ivas_stat_rend.h" +#include "isar_stat.h" /*----------------------------------------------------------------------------------* @@ -859,6 +860,7 @@ typedef struct renderer_struct } ISM_RENDERER_DATA, *ISM_RENDERER_HANDLE; +#ifndef SPLIT_REND_WITH_HEAD_ROT /* Fastconv binaural data structure */ typedef struct ivas_binaural_rendering_struct { @@ -882,8 +884,40 @@ typedef struct ivas_binaural_rendering_struct REVERB_STRUCT_HANDLE hReverb; } BINAURAL_RENDERER, *BINAURAL_RENDERER_HANDLE; +#endif +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*----------------------------------------------------------------------------------* + * IVAS decoder specific ISAR wrapper structures + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + +} ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA, *ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE; + +typedef struct +{ + Word32 Cldfb_RealBuffer_fx[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_fx[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + IVAS_AUDIO_CONFIG config; + +} ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA, *ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA_HANDLE; + +typedef struct +{ + ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE hMultiBinCldfbData; /*scratch buffer for frame by frame processing*/ + ISAR_SPLIT_REND_BITS_HANDLE hSplitRendBits; /*scratch buffer for frame by frame processing*/ + SPLIT_REND_WRAPPER splitrend; + ISAR_DEC_SPLIT_REND_CLDFB_OUT_DATA_HANDLE hCldfbDataOut; /*buffer to store cldfb data before binauralization*/ + Word16 numTdSamplesPerChannelCached; + +} ISAR_DEC_SPLIT_REND_WRAPPER, *ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE; +#endif + /*----------------------------------------------------------------------------------* * MASA decoder structures *----------------------------------------------------------------------------------*/ @@ -1029,7 +1063,9 @@ typedef struct decoder_config_structure int16_t Opt_tsm; /* indicates whether time scaling modification is activated */ IVAS_RENDER_FRAMESIZE render_framesize; int16_t Opt_delay_comp; /* flag indicating delay compensation active */ - +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t Opt_Limiter; +#endif } DECODER_CONFIG, *DECODER_CONFIG_HANDLE; @@ -1106,7 +1142,11 @@ typedef struct Decoder_Struct BINAURAL_RENDERER_HANDLE hBinRenderer; /* fastconv binaural renderer handle */ BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRendererTd; /* Time domain binaural object renderer handle */ TDREND_HRFILT_FiltSet_t *hHrtfTD; /* pointer to HRTF data for TD renderer */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + DIRAC_DEC_BIN_HANDLE hDiracDecBin[MAX_HEAD_ROT_POSES]; /* parametric binaural renderer handle */ +#else DIRAC_DEC_BIN_HANDLE hDiracDecBin; /* parametric binaural renderer handle */ +#endif LSSETUP_CONVERSION_HANDLE hLsSetUpConversion; /* MC LS configuration convertion handle */ EFAP_HANDLE hEFAPdata; /* EFAP structure */ VBAP_HANDLE hVBAPdata; /* VBAP structure */ @@ -1130,6 +1170,10 @@ typedef struct Decoder_Struct int16_t flag_omasa_brate; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; /* ISAR split binaural rendering handle */ + BINAURAL_TD_OBJECT_RENDERER_HANDLE hTdRendHandles[MAX_HEAD_ROT_POSES - 1]; +#endif /* JBM module */ DECODER_TC_BUFFER_HANDLE hTcBuffer; /* JBM structure */ diff --git a/lib_isar/isar_MSPred.c b/lib_isar/isar_MSPred.c new file mode 100644 index 000000000..4dea48a9b --- /dev/null +++ b/lib_isar/isar_MSPred.c @@ -0,0 +1,550 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include "options.h" +#include +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "isar_lcld_rom_tables.h" +#include "isar_lcld_prot.h" +#include "isar_prot.h" +#include "wmc_auto.h" +#include "basop_util.h" +#include "enh64.h" +#include +/*-------------------------------------------------------------------* + * Function _round() + * + * + *-------------------------------------------------------------------*/ + +static int32_t _round( + float val ) +{ + return ( val > 0.0f ? (int32_t) ( val + 0.5f ) : (int32_t) ( val - 0.5f ) ); +} + + +/*-------------------------------------------------------------------* + * Function quantPhase() + * + * + *-------------------------------------------------------------------*/ + +Word32 quantPhase_fx( + Word32 phase, + Word16 exp ) // i:31? +{ + Word32 phaseQ; + + // phaseQ = _round(phase * PHASE_QUANT_FACTOR); + phaseQ = L_shr_r( Mpy_32_32( phase, PHASE_QUANT_FACTOR_FX_Q29 ), 29 - exp ); // Q60 + if ( phaseQ == PHASE_MAX_VAL ) + { + phaseQ = PHASE_MIN_VAL; + } + return phaseQ; +} + +int32_t quantPhase( + float phase ) +{ + int32_t phaseQ; + + phaseQ = _round( phase * PHASE_QUANT_FACTOR ); + if ( phaseQ == PHASE_MAX_VAL ) + { + phaseQ = PHASE_MIN_VAL; + } + return phaseQ; +} + + +/*-------------------------------------------------------------------* + * Function cplxmult() + * + * + *-------------------------------------------------------------------*/ +void cplxmult_fx( + Word32 *pr1, + Word32 *pi1, + Word32 r2, + Word32 i2 ) +{ + Word32 r1 = *pr1, i1 = *pi1; + + *pr1 = L_sub( Mpy_32_32( r1, r2 ), Mpy_32_32( i1, i2 ) ); + *pi1 = L_add( Mpy_32_32( r1, i2 ), Mpy_32_32( i1, r2 ) ); + + return; +} +void cplxmult( + float *pr1, + float *pi1, + float r2, + float i2 ) +{ + float r1 = *pr1, i1 = *pi1; + + *pr1 = r1 * r2 - i1 * i2; + *pi1 = r1 * i2 + i1 * r2; + + return; +} +/*-------------------------------------------------------------------* + * Function requantPhase() + * + * + *-------------------------------------------------------------------*/ + +Word32 requantPhase( + Word32 phaseQ ) +{ + + IF( GE_32( phaseQ, PHASE_MAX_VAL ) ) + { + phaseQ = L_add( phaseQ, PHASE_MAX_VAL ); + phaseQ %= ( L_shl( PHASE_MAX_VAL, 1 ) ); + phaseQ = L_sub( phaseQ, PHASE_MAX_VAL ); + } + ELSE IF( LT_32( phaseQ, PHASE_MIN_VAL ) ) + { + phaseQ = L_sub( phaseQ, PHASE_MAX_VAL ); + phaseQ %= ( L_shl( PHASE_MAX_VAL, 1 ) ); + phaseQ = L_add( phaseQ, PHASE_MAX_VAL ); + IF( EQ_32( phaseQ, PHASE_MAX_VAL ) ) + { + phaseQ = PHASE_MIN_VAL; + move32(); + } + } + + return phaseQ; +} + + +/*-------------------------------------------------------------------* + * Function quantPred() + * + * + *-------------------------------------------------------------------*/ + +Word32 quantPred_fx( + const Word32 pred, + Word16 exp ) // i:Q31 +{ + // int32_t predQ = _round(pred * PRED_QUANT_FACTOR); + Word32 predQ = W_round32_s( W_shl( W_mult_32_32( pred, (Word32) PRED_QUANT_FACTOR ), exp ) ); + predQ = predQ > PRED_MAX_VAL ? PRED_MAX_VAL : predQ; + predQ = predQ < PRED_MIN_VAL ? PRED_MIN_VAL : predQ; + + return predQ; +} +int32_t quantPred( + const float pred ) +{ + int32_t predQ = _round( pred * PRED_QUANT_FACTOR ); + predQ = predQ > PRED_MAX_VAL ? PRED_MAX_VAL : predQ; + predQ = predQ < PRED_MIN_VAL ? PRED_MIN_VAL : predQ; + + return predQ; +} + + +/*-------------------------------------------------------------------* + * Function dequantPhase() + * + * + *-------------------------------------------------------------------*/ + +float dequantPhase( + const int32_t phaseQ ) +{ + return (float) phaseQ / PHASE_QUANT_FACTOR; +} + + +/*-------------------------------------------------------------------* + * Function dequantPred() + * + * + *-------------------------------------------------------------------*/ +Word32 dequantPred_fx( Word32 predQ ) +{ + if ( predQ == 12 ) + { + return MAX_32; + } + Word16 tmp_e; + Word32 tmp, value; + if ( predQ == 0 ) + { + return predQ; + } + tmp = BASOP_Util_Divide3216_Scale( predQ, PRED_QUANT_FACTOR_FX, &tmp_e ); + value = L_shl( tmp, sub( 31, negate( add( 1, tmp_e ) ) ) ); // Q31 + return value; +} +float dequantPred( int32_t predQ ) +{ + return (float) predQ / PRED_QUANT_FACTOR; +} + + +/*-------------------------------------------------------------------* + * Function PrepEncode() + * + * + *-------------------------------------------------------------------*/ + +Word32 PrepEncode( + Word32 *piQuant, + const Word32 *piMSFlags, + const Word32 numBands ) +{ + Word32 b, numMSBands; + numMSBands = 0; + move32(); + + FOR( b = 0; b < numBands; b++ ) + { + IF( piMSFlags[b] ) + { + piQuant[numMSBands++] = piQuant[b]; + move32(); + } + } + + FOR( b = numMSBands; b < numBands; b++ ) + { + piQuant[b] = 0; + move32(); + } + + return numMSBands; +} + + +/*-------------------------------------------------------------------* + * Function EncodePhase() + * + * + *-------------------------------------------------------------------*/ + +void EncodePhase( + Word32 *phaseQuant, + const Word32 numMSBands, + const Word32 diffDim ) +{ + Word32 b; + + IF( GT_32( diffDim, 0 ) ) + { + Word32 tmp1, tmp2; + tmp1 = phaseQuant[0]; + move32(); + FOR( b = 1; b < numMSBands; b++ ) + { + tmp2 = phaseQuant[b]; + move32(); + phaseQuant[b] = L_sub( phaseQuant[b], tmp1 ); + tmp1 = tmp2; + move32(); + } + } + + IF( GT_32( diffDim, 1 ) ) + { + Word32 tmp1, tmp2; + tmp1 = phaseQuant[1]; + move32(); + FOR( b = 2; b < numMSBands; b++ ) + { + tmp2 = phaseQuant[b]; + move32(); + phaseQuant[b] = L_sub( phaseQuant[b], tmp1 ); + tmp1 = tmp2; + move32(); + } + } + FOR( b = 1; b < numMSBands; b++ ) + { + phaseQuant[b] = requantPhase( phaseQuant[b] ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * Function DecodePhase() + * + * + *-------------------------------------------------------------------*/ + +void DecodePhase( + Word32 *phaseQuant, + const Word32 numMSBands, + const Word32 diffDim ) +{ + Word32 b; + + IF( GT_32( diffDim, 1 ) ) + { + FOR( b = 2; b < numMSBands; b++ ) + { + phaseQuant[b] = L_add( phaseQuant[b], phaseQuant[b - 1] ); + move32(); + } + } + + IF( GT_32( diffDim, 0 ) ) + { + FOR( b = 1; b < numMSBands; b++ ) + { + phaseQuant[b] = L_add( phaseQuant[b], phaseQuant[b - 1] ); + move32(); + } + } + + FOR( b = 1; b < numMSBands; b++ ) + { + phaseQuant[b] = requantPhase( phaseQuant[b] ); + move32(); + } + + return; +} + + +/*-------------------------------------------------------------------* + * Function EncodePredCoef() + * + * + *-------------------------------------------------------------------*/ + +Word32 EncodePredCoef( + Word32 *predQuant, + const Word32 numMSBands ) +{ + Word32 b, tmp1, tmp2; + + tmp1 = predQuant[0]; + move32(); + FOR( b = 1; b < numMSBands; b++ ) + { + tmp2 = predQuant[b]; + move32(); + predQuant[b] = L_sub( predQuant[b], tmp1 ); + tmp1 = tmp2; + move32(); + } + + return numMSBands; +} + + +/*-------------------------------------------------------------------* + * Function DecodePredCoef() + * + * + *-------------------------------------------------------------------*/ + +void DecodePredCoef( + Word32 *phaseQuant, + const Word32 numMSBands ) +{ + Word32 b; + + FOR( b = 1; b < numMSBands; b++ ) + { + phaseQuant[b] = L_add( phaseQuant[b], phaseQuant[b - 1] ); + } + + return; +} + + +/*-------------------------------------------------------------------* + * Function CountMSBits() + * + * + *-------------------------------------------------------------------*/ + +Word32 CountMSBits( + Word32 iNumBands, + const Word32 iMSMode, + const Word32 *piMSFlags, + const Word32 *piLRPhaseDiff, + const Word32 *piMSPredCoef ) +{ + Word32 iBitsWritten = 0; + move32(); + Word32 b; + Word32 anyNonZero; + Word32 iNumMSBands = 0; + move32(); + Word32 piPhaseCopy[MAX_BANDS_48]; + Word32 piPredCopy[MAX_BANDS_48]; + + FOR( b = 0; b < MAX_BANDS_48; b++ ) + { + piPhaseCopy[b] = 0; + move32(); + piPredCopy[b] = 0; + move32(); + } + + iBitsWritten = L_add( iBitsWritten, 2 ); /* iMSMode */ + FOR( b = 0; b < iNumBands; b++ ) + { + iNumMSBands = L_add( iNumMSBands, NE_32( piMSFlags[b], 0 ) ); + } + + IF( EQ_32( iNumMSBands, 0 ) ) + { + return iBitsWritten; + } + + IF( LT_32( iNumMSBands, iNumBands ) ) + { + iBitsWritten = L_add( iBitsWritten, iNumBands ); /* piMSFlags */ + } + + IF( LT_32( iMSMode, 3 ) ) + { + return iBitsWritten; + } + + /* prepare arrays for coding evaluation */ + FOR( b = 0; b < iNumBands; b++ ) + { + piPhaseCopy[b] = piLRPhaseDiff[b]; + move32(); + piPredCopy[b] = piMSPredCoef[b]; + move32(); + } + + /* Differential Coding of Phase Data*/ + PrepEncode( piPhaseCopy, piMSFlags, iNumBands ); + PrepEncode( piPredCopy, piMSFlags, iNumBands ); + EncodePhase( piPhaseCopy, iNumMSBands, PHASE_DIFF_DIM ); + EncodePredCoef( piPredCopy, iNumMSBands ); + + iBitsWritten = L_add( iBitsWritten, 1 ); /* iMSPredAll */ + anyNonZero = 0; /* phase */ + move32(); + FOR( b = 0; b < iNumMSBands; b++ ) + { + IF( NE_32( piPhaseCopy[b], 0 ) ) + { + anyNonZero = 1; + move32(); + BREAK; + } + } + iBitsWritten = L_add( iBitsWritten, 1 ); /*anyNonZero Phase*/ + IF( anyNonZero ) + { + iBitsWritten = L_add( iBitsWritten, PHASE_BAND0_BITS ); + FOR( b = 1; b < iNumMSBands; b++ ) + { + Word32 tabIdx = L_sub( piPhaseCopy[b], ENV_DELTA_MIN ); + iBitsWritten = L_add( iBitsWritten, c_aaiRMSEnvHuffEnc[tabIdx][0] ); + } + } + anyNonZero = 0; /* prediction */ + move32(); + FOR( b = 0; b < iNumMSBands; b++ ) + { + IF( NE_32( piPredCopy[b], 0 ) ) + { + anyNonZero = 1; + move32(); + break; + } + } + + iBitsWritten = L_add( iBitsWritten, 1 ); /* any nonZero Pred */ + IF( anyNonZero ) + { + iBitsWritten = L_add( iBitsWritten, PRED_BAND0_BITS ); + FOR( b = 1; b < iNumMSBands; b++ ) + { + Word32 tabIdx = L_sub( piPredCopy[b], ENV_DELTA_MIN ); + iBitsWritten = L_add( iBitsWritten, c_aaiRMSEnvHuffEnc[tabIdx][0] ); + } + } + + return iBitsWritten; +} + + +#ifdef DEBUG_WRITE_MS_PRED +void writeMSPred( + int32_t *phaseQuant, + int32_t *predQuant, + int32_t MSMode, + int32_t numMSBands, + int32_t numBands, + void *fid, + int32_t *piMsFlags ) +{ + int32_t b; + + fid = (FILE *) fid; + fprintf( fid, "%d %d", MSMode, numMSBands ); + for ( b = 0; b < numMSBands; b++ ) + { + fprintf( fid, " %d", phaseQuant[b] ); + } + for ( b = numMSBands; b < numBands; b++ ) + { + fprintf( fid, " %d", 0 ); + } + for ( b = 0; b < numMSBands; b++ ) + { + fprintf( fid, " %d", predQuant[b] ); + } + for ( b = numMSBands; b < numBands; b++ ) + { + fprintf( fid, " %d", 0 ); + } + for ( b = 0; b < numBands; b++ ) + { + fprintf( fid, " %d", piMsFlags[b] ); + } + fprintf( fid, "\n" ); + + return; +} +#endif +#endif diff --git a/lib_isar/isar_NoiseGen.c b/lib_isar/isar_NoiseGen.c new file mode 100644 index 000000000..a61f26fc2 --- /dev/null +++ b/lib_isar/isar_NoiseGen.c @@ -0,0 +1,58 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "prot.h" +#include "isar_lcld_prot.h" +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------------------------* + * Function DeleteNoiseGen() + * + * + *------------------------------------------------------------------------------------------*/ + +void DeleteNoiseGen( NoiseGen *psNoiseGen ) +{ + free( psNoiseGen->pfNoiseBuffer ); + free( psNoiseGen ); + + return; +} + +extern float GetNoise( NoiseGen *psNoiseGen ); +extern Word32 GetNoise_fx( NoiseGen *psNoiseGen ); +#endif diff --git a/lib_isar/isar_PerceptualModel.c b/lib_isar/isar_PerceptualModel.c new file mode 100644 index 000000000..85864ae0d --- /dev/null +++ b/lib_isar/isar_PerceptualModel.c @@ -0,0 +1,469 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "isar_lcld_prot.h" +#include "prot.h" +#include "isar_lcld_rom_tables.h" +#include +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ +#define PERCEPTUAL_MODEL_SCALE_SHIFT ( 6 ) +#define PERCEPTUAL_MODEL_SCALE ( 64 ) +#define PERCEPTUAL_MODEL_SCALE_SHIFT ( 6 ) +#define PERCEPTUAL_MODEL_ALPHA_SCALE ( 614 ) +#define PERCEPTUAL_MODEL_ALPHA_INV_SCALE ( 6827 ) +#define PERCEPTUAL_MODEL_ALPHA_SHIFT ( 11 ) + +/*------------------------------------------------------------------------------------------* + * Function LogAdd() + * + * + *------------------------------------------------------------------------------------------*/ + +static inline Word16 LogAdd_fx( + const Word16 iVal1, + const Word16 iVal2 ) +{ + Word16 iRetVal; + + IF( iVal1 > iVal2 ) + { + iRetVal = sub( iVal1, iVal2 ); + move16(); + iRetVal = ( iRetVal < sub( LOG_ADD_TABLE_LENGTH, 1 ) ) ? iRetVal : sub( LOG_ADD_TABLE_LENGTH, 1 ); + move16(); + iRetVal = add( iVal1, c_aiLogAddTable_fx[iRetVal] ); + move16(); + } + ELSE + { + iRetVal = sub( iVal2, iVal1 ); + move16(); + iRetVal = ( iRetVal < sub( LOG_ADD_TABLE_LENGTH, 1 ) ) ? iRetVal : sub( LOG_ADD_TABLE_LENGTH, 1 ); + move16(); + iRetVal = add( iVal2, c_aiLogAddTable_fx[iRetVal] ); + move16(); + } + + return iRetVal; +} +/*------------------------------------------------------------------------------------------* + * Function LogAdd() + * + * + *------------------------------------------------------------------------------------------*/ + +static inline int32_t LogAdd( + const int32_t iVal1, + const int32_t iVal2 ) +{ + int32_t iRetVal; + + if ( iVal1 > iVal2 ) + { + iRetVal = iVal1 - iVal2; + iRetVal = ( iRetVal < ( LOG_ADD_TABLE_LENGTH - 1 ) ) ? iRetVal : ( LOG_ADD_TABLE_LENGTH - 1 ); + iRetVal = iVal1 + c_aiLogAddTable[iRetVal]; + } + else + { + iRetVal = iVal2 - iVal1; + iRetVal = ( iRetVal < ( LOG_ADD_TABLE_LENGTH - 1 ) ) ? iRetVal : ( LOG_ADD_TABLE_LENGTH - 1 ); + iRetVal = iVal2 + c_aiLogAddTable[iRetVal]; + } + + return iRetVal; +} +/*------------------------------------------------------------------------------------------* + * Function PerceptualModel() + * + * + *------------------------------------------------------------------------------------------*/ + +void PerceptualModel_fx( + const Word32 iMaxQuantBands, + const Word32 *piRMSEnvelope, + Word32 *piExcitation, + Word32 *piSMR ) +{ + Word16 n; + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + Word16 iSLOffset; + + piExcitation[n] = shl( add( extract_l( piRMSEnvelope[n] ), c_aiBandwidthAdjust48_fx[n] ), PERCEPTUAL_MODEL_SCALE_SHIFT ); // shift instead of multiplying by PERCEPTUAL_MODEL_SCALE + move16(); + /* Calculate sensation level offset */ + iSLOffset = (Word16) extract_l( L_shr( L_mult0( c_aiDefaultTheta48_fx[n], sub( extract_l( piExcitation[n] ), c_aiAbsoluteThresh48_fx[n] ) ), PERCEPTUAL_MODEL_SLGAIN_SHIFT ) ); + // iSLOffset = (iSLOffset > 0) ? iSLOffset : 0; + move16(); + /* Offset envelope by sensation level offset */ + piExcitation[n] = sub( extract_l( piExcitation[n] ), iSLOffset ); + move16(); + /* Convert to loudness domain (x^0.3) */ + piExcitation[n] = extract_l( L_shr( L_mult0( PERCEPTUAL_MODEL_ALPHA_SCALE, extract_l( piExcitation[n] ) ), PERCEPTUAL_MODEL_ALPHA_SHIFT ) ); + move16(); + } + + /* Spread excitation function */ + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + Word16 k; + const Word16 *piSpread; + + piSpread = &c_aaiSpreadFunction48_fx[n * MAX_BANDS_48]; + move16(); + piSMR[n] = add( extract_l( piExcitation[n] ), piSpread[n] ); + move16(); + FOR( k = 0; k < iMaxQuantBands; k++ ) + { + IF( NE_16( k, n ) ) + { + piSMR[n] = L_deposit_l( LogAdd_fx( extract_l( piSMR[n] ), add( extract_l( piExcitation[k] ), piSpread[k] ) ) ); + move16(); + } + } + } + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + piSMR[n] = extract_l( L_shr( L_mult0( PERCEPTUAL_MODEL_ALPHA_INV_SCALE, extract_l( piSMR[n] ) ), PERCEPTUAL_MODEL_ALPHA_SHIFT ) ); + move16(); + piSMR[n] = shl( sub( add( extract_l( piRMSEnvelope[n] ), c_aiBandwidthAdjust48_fx[n] ), extract_l( piSMR[n] ) ), PERCEPTUAL_MODEL_SCALE_SHIFT ); + move16(); + } + + return; +} +/*------------------------------------------------------------------------------------------* + * Function PerceptualModel() + * + * + *------------------------------------------------------------------------------------------*/ + +void PerceptualModel( + const int32_t iMaxQuantBands, + const int32_t *piRMSEnvelope, + int32_t *piExcitation, + int32_t *piSMR ) +{ + int32_t n; + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + int32_t iSLOffset; + + piExcitation[n] = PERCEPTUAL_MODEL_SCALE * piRMSEnvelope[n] + c_aiBandwidthAdjust48[n]; + + /* Calculate sensation level offset */ + iSLOffset = c_aiDefaultTheta48[n] * ( piExcitation[n] - c_aiAbsoluteThresh48[n] ) >> PERCEPTUAL_MODEL_SLGAIN_SHIFT; + // iSLOffset = (iSLOffset > 0) ? iSLOffset : 0; + + /* Offset envelope by sensation level offset */ + piExcitation[n] -= iSLOffset; + + /* Convert to loudness domain (x^0.3) */ + piExcitation[n] = PERCEPTUAL_MODEL_ALPHA_SCALE * piExcitation[n] >> PERCEPTUAL_MODEL_ALPHA_SHIFT; + } + + /* Spread excitation function */ + for ( n = 0; n < iMaxQuantBands; n++ ) + { + int32_t k; + const int32_t *piSpread; + + piSpread = &c_aaiSpreadFunction48[n * MAX_BANDS_48]; + piSMR[n] = piExcitation[n] + piSpread[n]; + for ( k = 0; k < iMaxQuantBands; k++ ) + { + if ( k != n ) + { + piSMR[n] = LogAdd( piSMR[n], piExcitation[k] + piSpread[k] ); + } + } + } + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + piSMR[n] = PERCEPTUAL_MODEL_ALPHA_INV_SCALE * piSMR[n] >> PERCEPTUAL_MODEL_ALPHA_SHIFT; + piSMR[n] = PERCEPTUAL_MODEL_SCALE * piRMSEnvelope[n] + c_aiBandwidthAdjust48[n] - piSMR[n]; + } + + return; +} +/*------------------------------------------------------------------------------------------* + * Function PerceptualModelStereo() + * + * + *------------------------------------------------------------------------------------------*/ + +void PerceptualModelStereo( + const int32_t iMaxQuantBands, + const int32_t *piMSFlags, + const int32_t *piRMSEnvelope0, + const int32_t *piRMSEnvelope1, + int32_t *piExcitation0, + int32_t *piExcitation1, + int32_t *piSMR0, + int32_t *piSMR1 ) +{ + int32_t n; + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + int32_t iMaxRMSEnv; + int32_t iSLOffset; + + iMaxRMSEnv = piRMSEnvelope0[n]; + + piExcitation0[n] = PERCEPTUAL_MODEL_SCALE * iMaxRMSEnv + c_aiBandwidthAdjust48[n]; /* piRMSEnvelope0[n] */ + + /* Calculate sensation level offset */ + iSLOffset = c_aiDefaultTheta48[n] * ( piExcitation0[n] - c_aiAbsoluteThresh48[n] ) >> PERCEPTUAL_MODEL_SLGAIN_SHIFT; + // iSLOffset = (iSLOffset > 0) ? iSLOffset : 0; + + /* Offset envelope by sensation level offset */ + piExcitation0[n] -= iSLOffset; + + /* Convert to loudness domain (x^0.3) */ + piExcitation0[n] = PERCEPTUAL_MODEL_ALPHA_SCALE * piExcitation0[n] >> PERCEPTUAL_MODEL_ALPHA_SHIFT; + } + + /* Spread excitation function */ + for ( n = 0; n < iMaxQuantBands; n++ ) + { + int32_t k; + const int32_t *piSpread; + + piSpread = &c_aaiSpreadFunction48[n * MAX_BANDS_48]; + piSMR0[n] = piExcitation0[n] + piSpread[n]; + for ( k = 0; k < iMaxQuantBands; k++ ) + { + if ( k != n ) + { + piSMR0[n] = LogAdd( piSMR0[n], piExcitation0[k] + piSpread[k] ); + } + } + } + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + int32_t iMaxRMSEnv; + int32_t iSLOffset; + + iMaxRMSEnv = piRMSEnvelope1[n]; + + piExcitation1[n] = PERCEPTUAL_MODEL_SCALE * iMaxRMSEnv + c_aiBandwidthAdjust48[n]; /* piRMSEnvelope1[n] */ + + /* Calculate sensation level offset */ + iSLOffset = c_aiDefaultTheta48[n] * ( piExcitation1[n] - c_aiAbsoluteThresh48[n] ) >> PERCEPTUAL_MODEL_SLGAIN_SHIFT; + // iSLOffset = (iSLOffset > 0) ? iSLOffset : 0; + + /* Offset envelope by sensation level offset */ + piExcitation1[n] -= iSLOffset; + + /* Convert to loudness domain (x^0.3) */ + piExcitation1[n] = PERCEPTUAL_MODEL_ALPHA_SCALE * piExcitation1[n] >> PERCEPTUAL_MODEL_ALPHA_SHIFT; + } + + /* Spread excitation function */ + for ( n = 0; n < iMaxQuantBands; n++ ) + { + int32_t k; + const int32_t *piSpread; + + piSpread = &c_aaiSpreadFunction48[n * MAX_BANDS_48]; + piSMR1[n] = piExcitation1[n] + piSpread[n]; + for ( k = 0; k < iMaxQuantBands; k++ ) + { + if ( k != n ) + { + piSMR1[n] = LogAdd( piSMR1[n], piExcitation1[k] + piSpread[k] ); + } + } + } + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + if ( piMSFlags[n] == 1 ) + { + piSMR0[n] = ( piSMR0[n] > piSMR1[n] ) ? piSMR0[n] : piSMR1[n]; + piSMR1[n] = piSMR0[n]; + } + } + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + piSMR0[n] = PERCEPTUAL_MODEL_ALPHA_INV_SCALE * piSMR0[n] >> PERCEPTUAL_MODEL_ALPHA_SHIFT; + piSMR0[n] = PERCEPTUAL_MODEL_SCALE * piRMSEnvelope0[n] + c_aiBandwidthAdjust48[n] - piSMR0[n]; + } + + for ( n = 0; n < iMaxQuantBands; n++ ) + { + piSMR1[n] = PERCEPTUAL_MODEL_ALPHA_INV_SCALE * piSMR1[n] >> PERCEPTUAL_MODEL_ALPHA_SHIFT; + piSMR1[n] = PERCEPTUAL_MODEL_SCALE * piRMSEnvelope1[n] + c_aiBandwidthAdjust48[n] - piSMR1[n]; + } + + return; +} +void PerceptualModelStereo_fx( + const Word32 iMaxQuantBands, + const Word32 *piMSFlags, + const Word32 *piRMSEnvelope0, + const Word32 *piRMSEnvelope1, + Word32 *piExcitation0, + Word32 *piExcitation1, + Word32 *piSMR0, + Word32 *piSMR1 ) +{ + Word16 n; + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + Word16 iMaxRMSEnv; + Word16 iSLOffset; + + iMaxRMSEnv = extract_l( piRMSEnvelope0[n] ); + move16(); + piExcitation0[n] = add( shl( iMaxRMSEnv, PERCEPTUAL_MODEL_SCALE_SHIFT ), c_aiBandwidthAdjust48_fx[n] ); /* piRMSEnvelope0[n] */ + move16(); + /* Calculate sensation level offset */ + iSLOffset = extract_l( L_shr( L_mult0( c_aiDefaultTheta48_fx[n], sub( extract_l( piExcitation0[n] ), c_aiAbsoluteThresh48_fx[n] ) ), PERCEPTUAL_MODEL_SLGAIN_SHIFT ) ); + // iSLOffset = (iSLOffset > 0) ? iSLOffset : 0; + move16(); + /* Offset envelope by sensation level offset */ + piExcitation0[n] = sub( extract_l( piExcitation0[n] ), iSLOffset ); + move16(); + /* Convert to loudness domain (x^0.3) */ + piExcitation0[n] = extract_l( L_shr( L_mult0( PERCEPTUAL_MODEL_ALPHA_SCALE, extract_l( piExcitation0[n] ) ), PERCEPTUAL_MODEL_ALPHA_SHIFT ) ); + move16(); + } + + /* Spread excitation function */ + for ( n = 0; n < iMaxQuantBands; n++ ) + { + Word16 k; + const Word16 *piSpread; + + piSpread = &c_aaiSpreadFunction48_fx[n * MAX_BANDS_48]; + move16(); + piSMR0[n] = add( extract_l( piExcitation0[n] ), piSpread[n] ); + move16(); + FOR( k = 0; k < iMaxQuantBands; k++ ) + { + IF( NE_16( k, n ) ) + { + piSMR0[n] = L_deposit_l( LogAdd_fx( extract_l( piSMR0[n] ), add( extract_l( piExcitation0[k] ), piSpread[k] ) ) ); + move16(); + } + } + } + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + Word16 iMaxRMSEnv; + Word16 iSLOffset; + + iMaxRMSEnv = extract_l( piRMSEnvelope1[n] ); + move16(); + piExcitation1[n] = add( shl( iMaxRMSEnv, PERCEPTUAL_MODEL_SCALE_SHIFT ), c_aiBandwidthAdjust48_fx[n] ); /* piRMSEnvelope1[n] */ + move16(); + /* Calculate sensation level offset */ + iSLOffset = extract_l( L_shr( L_mult0( c_aiDefaultTheta48_fx[n], sub( extract_l( piExcitation1[n] ), c_aiAbsoluteThresh48_fx[n] ) ), PERCEPTUAL_MODEL_SLGAIN_SHIFT ) ); + // iSLOffset = (iSLOffset > 0) ? iSLOffset : 0; + move16(); + /* Offset envelope by sensation level offset */ + piExcitation1[n] = sub( extract_l( piExcitation1[n] ), iSLOffset ); + move16(); + /* Convert to loudness domain (x^0.3) */ + piExcitation1[n] = extract_l( L_shr( L_mult0( PERCEPTUAL_MODEL_ALPHA_SCALE, extract_l( piExcitation1[n] ) ), PERCEPTUAL_MODEL_ALPHA_SHIFT ) ); + move16(); + } + + /* Spread excitation function */ + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + Word16 k; + const Word16 *piSpread; + + piSpread = &c_aaiSpreadFunction48_fx[n * MAX_BANDS_48]; + move16(); + piSMR1[n] = add( extract_l( piExcitation1[n] ), piSpread[n] ); + move16(); + FOR( k = 0; k < iMaxQuantBands; k++ ) + { + IF( NE_16( k, n ) ) + { + piSMR1[n] = LogAdd_fx( extract_l( piSMR1[n] ), add( extract_l( piExcitation1[k] ), piSpread[k] ) ); + move16(); + } + } + } + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + IF( EQ_16( extract_l( piMSFlags[n] ), 1 ) ) + { + piSMR0[n] = ( piSMR0[n] > piSMR1[n] ) ? piSMR0[n] : piSMR1[n]; + move16(); + piSMR1[n] = piSMR0[n]; + move16(); + } + } + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + piSMR0[n] = extract_l( L_shr( L_mult0( PERCEPTUAL_MODEL_ALPHA_INV_SCALE, extract_l( piSMR0[n] ) ), PERCEPTUAL_MODEL_ALPHA_SHIFT ) ); + move16(); + piSMR0[n] = sub( add( shl( extract_l( piRMSEnvelope0[n] ), PERCEPTUAL_MODEL_SCALE_SHIFT ), c_aiBandwidthAdjust48_fx[n] ), extract_l( piSMR0[n] ) ); + move16(); + } + + FOR( n = 0; n < iMaxQuantBands; n++ ) + { + piSMR1[n] = extract_l( L_shr( L_mult0( PERCEPTUAL_MODEL_ALPHA_INV_SCALE, extract_l( piSMR1[n] ) ), PERCEPTUAL_MODEL_ALPHA_SHIFT ) ); + move16(); + piSMR1[n] = sub( add( shl( extract_l( piRMSEnvelope1[n] ), PERCEPTUAL_MODEL_SCALE_SHIFT ), c_aiBandwidthAdjust48_fx[n] ), extract_l( piSMR1[n] ) ); + move16(); + } + + return; +} +#endif diff --git a/lib_isar/isar_PredDecoder.c b/lib_isar/isar_PredDecoder.c new file mode 100644 index 000000000..3fa9ec877 --- /dev/null +++ b/lib_isar/isar_PredDecoder.c @@ -0,0 +1,496 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "prot.h" +#include "isar_prot.h" +#include "isar_lcld_prot.h" +#include "isar_lcld_rom_tables.h" +#include "wmc_auto.h" +#include "basop_mpy.h" + +/*-------------------------------------------------------------------* + * Function CreatePredictionDecoder() + * + * + *-------------------------------------------------------------------*/ + +ivas_error CreatePredictionDecoder_fx( + PredictionDecoder **psPredictionDecoder_out, + const Word32 iChannels, + const Word32 iNumBlocks ) +{ + Word16 n; + Word16 m; + PredictionDecoder *psPredictionDecoder = NULL; + + IF( ( psPredictionDecoder = (PredictionDecoder *) malloc( sizeof( PredictionDecoder ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + psPredictionDecoder->iChannels = iChannels; + move32(); + psPredictionDecoder->iNumBlocks = iNumBlocks; + move32(); + psPredictionDecoder->iNumSubSets = LCLD_BLOCKS_PER_FRAME / psPredictionDecoder->iNumBlocks; + move32(); + psPredictionDecoder->iSubSetId = 0; + move32(); + /* PLC_IMPROVEMENT */ + IF( ( psPredictionDecoder->ppiDecodingFailedPrev = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiDecodingFailed = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiDecodingUnresolved = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + FOR( n = 0; n < iChannels; n++ ) + { + Word32 k; + IF( ( psPredictionDecoder->ppiDecodingUnresolved[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_MAX_NUM_PRED_SUBSETS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiDecodingFailed[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_MAX_NUM_PRED_SUBSETS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiDecodingFailedPrev[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_MAX_NUM_PRED_SUBSETS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + FOR( k = 0; k < LCLD_MAX_NUM_PRED_SUBSETS; k++ ) + { + psPredictionDecoder->ppiDecodingUnresolved[n][k] = 0; + move32(); + psPredictionDecoder->ppiDecodingFailed[n][k] = 0; + move32(); + psPredictionDecoder->ppiDecodingFailedPrev[n][k] = 0; + move32(); + } + } + IF( ( psPredictionDecoder->piPredChanEnable = (Word32 *) malloc( sizeof( Word32 ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiPredBandEnable = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfA1Real_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfA1Imag_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiA1Mag = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiA1Phase = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfPredStateReal_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfPredStateImag_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + + FOR( n = 0; n < psPredictionDecoder->iChannels; n++ ) + { + psPredictionDecoder->piPredChanEnable[n] = 0; + move32(); + IF( ( psPredictionDecoder->ppiPredBandEnable[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + FOR( m = 0; m < LCLD_BANDS; m++ ) + { + psPredictionDecoder->ppiPredBandEnable[n][m] = 0; + move32(); + } + IF( ( psPredictionDecoder->ppfA1Real_fx[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfA1Imag_fx[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiA1Mag[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppiA1Phase[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfPredStateReal_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionDecoder Module \n" ) ); + } + IF( ( psPredictionDecoder->ppfPredStateImag_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionDecoder Module \n" ) ); + } + FOR( m = 0; m < LCLD_BANDS; m++ ) + { + psPredictionDecoder->ppfPredStateReal_fx[n][m] = 0; + move32(); + psPredictionDecoder->ppfPredStateImag_fx[n][m] = 0; + move32(); + } + } + + /* pre-define these tables? */ + + FOR( n = 0; n < ( 1 << PRED_QUNAT_FILTER_MAG_BITS ); n++ ) + { + psPredictionDecoder->pfMagLUT_fx[n] = c_pfMagLUT[n]; /* Q31 */ + move32(); + } + + FOR( n = 0; n < ( 1 << PRED_QUANT_FILTER_PHASE_BITS ); n++ ) + { + psPredictionDecoder->pfP2RRealLUT_fx[n] = c_pfP2RRealLUT[n]; /* Q31 */ + move32(); + psPredictionDecoder->pfP2RImagLUT_fx[n] = c_pfP2RImagLUT[n]; /* Q31 */ + move32(); + } + + *psPredictionDecoder_out = psPredictionDecoder; + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * Function DeletePredictionDecoder() + * + * + *-------------------------------------------------------------------*/ + +void DeletePredictionDecoder_fx( + PredictionDecoder *psPredictionDecoder ) +{ + Word32 n; + + FOR( n = 0; n < psPredictionDecoder->iChannels; n++ ) + { + free( psPredictionDecoder->ppiPredBandEnable[n] ); + free( psPredictionDecoder->ppfA1Real_fx[n] ); + free( psPredictionDecoder->ppfA1Imag_fx[n] ); + free( psPredictionDecoder->ppiA1Mag[n] ); + free( psPredictionDecoder->ppiA1Phase[n] ); + free( psPredictionDecoder->ppfPredStateReal_fx[n] ); + free( psPredictionDecoder->ppfPredStateImag_fx[n] ); + free( psPredictionDecoder->ppiDecodingUnresolved[n] ); + free( psPredictionDecoder->ppiDecodingFailed[n] ); + free( psPredictionDecoder->ppiDecodingFailedPrev[n] ); + } + free( psPredictionDecoder->piPredChanEnable ); + free( psPredictionDecoder->ppiPredBandEnable ); + free( psPredictionDecoder->ppfA1Real_fx ); + free( psPredictionDecoder->ppfA1Imag_fx ); + free( psPredictionDecoder->ppiA1Mag ); + free( psPredictionDecoder->ppiA1Phase ); + free( psPredictionDecoder->ppfPredStateReal_fx ); + free( psPredictionDecoder->ppfPredStateImag_fx ); + /* PLC_IMPROVEMENT */ + free( psPredictionDecoder->ppiDecodingUnresolved ); + free( psPredictionDecoder->ppiDecodingFailed ); + free( psPredictionDecoder->ppiDecodingFailedPrev ); + + free( psPredictionDecoder ); + psPredictionDecoder = NULL; + + return; +} +/*-------------------------------------------------------------------* + * Function ReadPredictors() + * + * + *-------------------------------------------------------------------*/ + +Word32 ReadPredictors_fx( + PredictionDecoder *psPredictionDecoder, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word16 iBitsRead = 0; + Word32 c; + Word32 b; + Word16 iNumPredBandBits = 6; + const Word16 iSubSetBits = ( GT_32( LCLD_MAX_NUM_PRED_SUBSETS, 4 ) ? 3 : 2 ); + move16(); + move16(); + move16(); + + psPredictionDecoder->iNumSubSets = L_add( ISAR_SPLIT_REND_BITStream_read_int32( pBits, iSubSetBits ), 1 ); + iBitsRead = add( iBitsRead, iSubSetBits ); + + IF( GT_32( psPredictionDecoder->iNumSubSets, 1 ) ) + { + psPredictionDecoder->iSubSetId = ISAR_SPLIT_REND_BITStream_read_int32( pBits, iSubSetBits ); + iBitsRead = add( iBitsRead, iSubSetBits ); + iNumPredBandBits = ( GE_32( psPredictionDecoder->iNumSubSets, 4 ) ? 4 : 5 ); + move16(); + } + ELSE + { + psPredictionDecoder->iSubSetId = 0; + move32(); + } + FOR( c = 0; c < psPredictionDecoder->iChannels; c++ ) + { + psPredictionDecoder->piPredChanEnable[c] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, psPredictionDecoder->iNumSubSets ); + move32(); + iBitsRead = add( iBitsRead, (Word16) psPredictionDecoder->iNumSubSets ); + + IF( get_bit( psPredictionDecoder->piPredChanEnable[c], psPredictionDecoder->iSubSetId ) ) + { + Word32 b0 = psPredictionDecoder->iSubSetId; + Word32 bstep = psPredictionDecoder->iNumSubSets; + Word32 iNumPredBands; + move32(); + move32(); + + FOR( b = b0; b < LCLD_BANDS; b = L_add( b, bstep ) ) + { + psPredictionDecoder->ppiPredBandEnable[c][b] = 0; + move32(); + } + iNumPredBands = ISAR_SPLIT_REND_BITStream_read_int32( pBits, iNumPredBandBits ); + iBitsRead = add( iBitsRead, iNumPredBandBits ); + iNumPredBands = L_add( L_mult0( (Word16) iNumPredBands, (Word16) psPredictionDecoder->iNumSubSets ), b0 ); + + FOR( b = b0; b < iNumPredBands; b = L_add( b, bstep ) ) + { + psPredictionDecoder->ppiPredBandEnable[c][b] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + move32(); + iBitsRead = add( iBitsRead, 1 ); + + IF( EQ_32( psPredictionDecoder->ppiPredBandEnable[c][b], 1 ) ) + { + Word32 iA1Mag; + Word32 iA1Phase; + Word32 fA1Real; + Word32 fA1Imag; + iA1Mag = ISAR_SPLIT_REND_BITStream_read_int32( pBits, PRED_QUNAT_FILTER_MAG_BITS ); + iBitsRead = add( iBitsRead, PRED_QUNAT_FILTER_MAG_BITS ); + iA1Phase = ISAR_SPLIT_REND_BITStream_read_int32( pBits, PRED_QUANT_FILTER_PHASE_BITS ); + iBitsRead = add( iBitsRead, PRED_QUANT_FILTER_PHASE_BITS ); + + psPredictionDecoder->ppiA1Mag[c][b] = iA1Mag; + move32(); + psPredictionDecoder->ppiA1Phase[c][b] = L_add( iA1Phase, PRED_QUANT_FILTER_PHASE_MIN ); + move32(); + + fA1Real = Mpy_32_32( psPredictionDecoder->pfMagLUT_fx[iA1Mag], psPredictionDecoder->pfP2RRealLUT_fx[iA1Phase] ); /* Q31 */ + fA1Imag = Mpy_32_32( psPredictionDecoder->pfMagLUT_fx[iA1Mag], psPredictionDecoder->pfP2RImagLUT_fx[iA1Phase] ); /* Q31 */ + + psPredictionDecoder->ppfA1Real_fx[c][b] = fA1Real; /* Q31 */ + move32(); + psPredictionDecoder->ppfA1Imag_fx[c][b] = fA1Imag; /* Q31 */ + move32(); + } + } + } + } + + /* disable any inactive prediction bands */ + FOR( c = 0; c < psPredictionDecoder->iChannels; c++ ) + { + Word32 set; + FOR( set = 0; set < psPredictionDecoder->iNumSubSets; set++ ) + { + IF( !get_bit( psPredictionDecoder->piPredChanEnable[c], set ) ) + { + FOR( b = set; b < LCLD_BANDS; b = L_add( b, psPredictionDecoder->iNumSubSets ) ) + { + psPredictionDecoder->ppiPredBandEnable[c][b] = 0; + move32(); + } + } + } + } + + return iBitsRead; +} +/* PLC_IMPROVEMENT */ +void SetDecodingPassed( PredictionDecoder *psPredictionDecoder ) +{ + int32_t n, ch; + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + psPredictionDecoder->ppiDecodingFailed[ch][n] = 0; + } + } +} +int32_t AnyDecodingUnresolved( PredictionDecoder *psPredictionDecoder ) +{ + int32_t n, ch; + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + if ( psPredictionDecoder->ppiDecodingUnresolved[ch][n] == 1 ) + { + return 1; + } + } + } + return 0; +} + +void UpdateDecodingFailedStatus( PredictionDecoder *psPredictionDecoder ) +{ + int32_t n, ch; + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + psPredictionDecoder->ppiDecodingFailedPrev[ch][n] = psPredictionDecoder->ppiDecodingFailed[ch][n]; + } + } +} + +void UpdateDecodingUnresolved( PredictionDecoder *psPredictionDecoder ) +{ + int32_t n, ch; + + int32_t iCurrentSubSet = psPredictionDecoder->iSubSetId; + + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + /* Prediction data always available for current subset */ + psPredictionDecoder->ppiDecodingUnresolved[ch][iCurrentSubSet] = 0; + + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + int32_t iSubSetActive = get_bit( psPredictionDecoder->piPredChanEnable[ch], n ); + if ( iSubSetActive == 0 ) + { + /* Prediction information available inactive subsets (e.g. no Prediction) */ + psPredictionDecoder->ppiDecodingUnresolved[ch][n] = 0; + } + } + } +} + +/*-------------------------------------------------------------------* + * Function ApplyInversePredictors() + * + * + *-------------------------------------------------------------------*/ + +void ApplyInversePredictors_fx( + PredictionDecoder *psPredictionDecoder, + Word32 ***pppfReal, + Word32 ***pppfImag ) +{ + Word32 c; + FOR( c = 0; c < psPredictionDecoder->iChannels; c++ ) + { + IF( GT_32( psPredictionDecoder->piPredChanEnable[c], 0 ) ) + { + Word32 b; + FOR( b = 0; b < LCLD_BANDS; b++ ) + { + IF( EQ_32( psPredictionDecoder->ppiPredBandEnable[c][b], 1 ) ) + { + Word32 n; + Word32 fA1Real; + Word32 fA1Imag; + Word32 fPrevReal = 0; + move32(); + Word32 fPrevImag = 0; + move32(); + Word32 iSubset = b % psPredictionDecoder->iNumSubSets; + + IF( NE_32( iSubset, psPredictionDecoder->iSubSetId ) ) + { + fPrevReal = psPredictionDecoder->ppfPredStateReal_fx[c][b]; + move32(); + fPrevImag = psPredictionDecoder->ppfPredStateImag_fx[c][b]; + move32(); + } + + fA1Real = psPredictionDecoder->ppfA1Real_fx[c][b]; + move32(); + fA1Imag = psPredictionDecoder->ppfA1Imag_fx[c][b]; + move32(); + FOR( n = 0; n < psPredictionDecoder->iNumBlocks; n++ ) + { + Word32 fReal; + Word32 fImag; + + fReal = L_add( L_sub( pppfReal[c][n][b], Mpy_32_32( fA1Real, fPrevReal ) ), Mpy_32_32( fA1Imag, fPrevImag ) ); + fImag = L_sub( L_sub( pppfImag[c][n][b], Mpy_32_32( fA1Real, fPrevImag ) ), Mpy_32_32( fA1Imag, fPrevReal ) ); + + pppfReal[c][n][b] = fReal; + move32(); + pppfImag[c][n][b] = fImag; + move32(); + + fPrevReal = fReal; + move32(); + fPrevImag = fImag; + move32(); + } + psPredictionDecoder->ppfPredStateReal_fx[c][b] = fPrevReal; + move32(); + psPredictionDecoder->ppfPredStateImag_fx[c][b] = fPrevImag; + move32(); + } + } + } + } + + return; +} +#endif diff --git a/lib_isar/isar_PredEncoder.c b/lib_isar/isar_PredEncoder.c new file mode 100644 index 000000000..0ca4d7add --- /dev/null +++ b/lib_isar/isar_PredEncoder.c @@ -0,0 +1,1215 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "isar_lcld_prot.h" +#include "isar_lcld_rom_tables.h" +#include "prot.h" +#include "isar_prot.h" +#include "wmc_auto.h" +#include "prot_fx2.h" +#include "basop_util.h" +#include "enh64.h" +#include "basop32.h" + + +/*-------------------------------------------------------------------* + * Function activate_bit() + * + * + *-------------------------------------------------------------------*/ +static void activate_bit( + Word32 *state, + const Word32 bit_id ) +{ + ( *state ) = L_or( ( *state ), L_shl( 1, extract_l( bit_id ) ) ); +} + +/*-------------------------------------------------------------------* + * Function deactivate_bit() + * + * + *-------------------------------------------------------------------*/ + +static void deactivate_bit( + Word32 *state, + const Word32 bit_id ) +{ + ( *state ) = L_and( ( *state ), ~L_shl( 1, extract_l( bit_id ) ) ); +} +void UpdatePredictionSubSetId( PredictionEncoder *psPredictionEncoder ) +{ + IF( EQ_32( ++psPredictionEncoder->iSubSetId, psPredictionEncoder->iNumSubSets ) ) + { + psPredictionEncoder->iSubSetId = 0; + move32(); + } +} +/*-------------------------------------------------------------------* + * Function CreatePredictionEncoder() + * + * + *-------------------------------------------------------------------*/ + +ivas_error CreatePredictionEncoder_fx( + PredictionEncoder **psPredictionEncoder_out, + const Word32 iChannels, + const Word32 iNumBlocks, + const Word32 iNumSubSets, + const Word32 iMaxNumPredBands ) +{ + Word32 k, n; + PredictionEncoder *psPredictionEncoder = NULL; + + IF( ( psPredictionEncoder = (PredictionEncoder *) malloc( sizeof( PredictionEncoder ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + psPredictionEncoder->iChannels = iChannels; + move32(); + psPredictionEncoder->iNumBlocks = iNumBlocks; + move32(); + psPredictionEncoder->iSubSetId = 0; + move32(); + psPredictionEncoder->iMaxNumPredBands = iMaxNumPredBands; + move32(); + psPredictionEncoder->iNumSubSets = iNumSubSets; + move32(); + IF( ( psPredictionEncoder->piPredChanEnable = (Word32 *) malloc( sizeof( Word32 ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + IF( ( psPredictionEncoder->piNumPredBands = (Word32 *) malloc( sizeof( Word32 ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + FOR( n = 0; n < psPredictionEncoder->iChannels; n++ ) + { + psPredictionEncoder->piPredChanEnable[n] = 0; + move32(); + psPredictionEncoder->piNumPredBands[n] = 40; // Will need to be set correctly + move32(); + } + + IF( ( psPredictionEncoder->ppiPredBandEnable = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfA1Real_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfA1Imag_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppiA1Mag = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppiA1Phase = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->pppfInpBufReal_fx = (Word32 ***) malloc( sizeof( Word32 ** ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->pppfInpBufImag_fx = (Word32 ***) malloc( sizeof( Word32 ** ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfInpPrevReal_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfInpPrevImag_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfPredStateReal_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfPredStateImag_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfPredStateRealTmp_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfPredStateImagTmp_fx = (Word32 **) malloc( sizeof( Word32 * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + FOR( n = 0; n < psPredictionEncoder->iChannels; n++ ) + { + IF( ( psPredictionEncoder->ppiPredBandEnable[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfA1Real_fx[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfA1Imag_fx[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppiA1Mag[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppiA1Phase[n] = (Word32 *) malloc( sizeof( Word32 ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->pppfInpBufReal_fx[n] = (Word32 **) malloc( sizeof( Word32 * ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->pppfInpBufImag_fx[n] = (Word32 **) malloc( sizeof( Word32 * ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + FOR( k = 0; k < LCLD_PRED_WIN_LEN; k++ ) + { + IF( ( psPredictionEncoder->pppfInpBufReal_fx[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->pppfInpBufImag_fx[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set32_fx( psPredictionEncoder->pppfInpBufReal_fx[n][k], 0, LCLD_BANDS ); + set32_fx( psPredictionEncoder->pppfInpBufImag_fx[n][k], 0, LCLD_BANDS ); + } + IF( ( psPredictionEncoder->ppfPredStateReal_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfPredStateImag_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set32_fx( psPredictionEncoder->ppfPredStateReal_fx[n], 0, LCLD_BANDS ); + set32_fx( psPredictionEncoder->ppfPredStateImag_fx[n], 0, LCLD_BANDS ); + + IF( ( psPredictionEncoder->ppfInpPrevReal_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfInpPrevImag_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + set32_fx( psPredictionEncoder->ppfInpPrevReal_fx[n], 0, LCLD_BANDS ); + set32_fx( psPredictionEncoder->ppfInpPrevImag_fx[n], 0, LCLD_BANDS ); + + IF( ( psPredictionEncoder->ppfPredStateRealTmp_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + IF( ( psPredictionEncoder->ppfPredStateImagTmp_fx[n] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set32_fx( psPredictionEncoder->ppfPredStateRealTmp_fx[n], 0, LCLD_BANDS ); + set32_fx( psPredictionEncoder->ppfPredStateImagTmp_fx[n], 0, LCLD_BANDS ); + FOR( k = 0; k < LCLD_BANDS; k++ ) + { + psPredictionEncoder->ppiPredBandEnable[n][k] = 0; + move32(); + psPredictionEncoder->ppfA1Real_fx[n][k] = 0; + move32(); + psPredictionEncoder->ppfA1Imag_fx[n][k] = 0; + move32(); + } + } + + *psPredictionEncoder_out = psPredictionEncoder; + + return IVAS_ERR_OK; +} +ivas_error CreatePredictionEncoder( + PredictionEncoder **psPredictionEncoder_out, + const int32_t iChannels, + const int32_t iNumBlocks, + const int32_t iNumSubSets, + const int32_t iMaxNumPredBands ) +{ + int32_t k, n; + PredictionEncoder *psPredictionEncoder = NULL; + + if ( ( psPredictionEncoder = (PredictionEncoder *) malloc( sizeof( PredictionEncoder ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + psPredictionEncoder->iChannels = iChannels; + psPredictionEncoder->iNumBlocks = iNumBlocks; + psPredictionEncoder->iSubSetId = 0; + psPredictionEncoder->iMaxNumPredBands = iMaxNumPredBands; + psPredictionEncoder->iNumSubSets = iNumSubSets; + + if ( ( psPredictionEncoder->piPredChanEnable = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + if ( ( psPredictionEncoder->piNumPredBands = (int32_t *) malloc( sizeof( int32_t ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) + { + psPredictionEncoder->piPredChanEnable[n] = 0; + psPredictionEncoder->piNumPredBands[n] = 40; // Will need to be set correctly + } + + if ( ( psPredictionEncoder->ppiPredBandEnable = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfA1Real = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfA1Imag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppiA1Mag = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppiA1Phase = (int32_t **) malloc( sizeof( int32_t * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufReal = (float ***) malloc( sizeof( float ** ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufImag = (float ***) malloc( sizeof( float ** ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfInpPrevReal = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfInpPrevImag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateReal = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImag = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateRealTmp = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImagTmp = (float **) malloc( sizeof( float * ) * iChannels ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) + { + if ( ( psPredictionEncoder->ppiPredBandEnable[n] = (int32_t *) malloc( sizeof( int32_t ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfA1Real[n] = (float *) malloc( sizeof( float ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfA1Imag[n] = (float *) malloc( sizeof( float ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppiA1Mag[n] = (int32_t *) malloc( sizeof( int32_t ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppiA1Phase[n] = (int32_t *) malloc( sizeof( int32_t ) * LCLD_BANDS ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufReal[n] = (float **) malloc( sizeof( float * ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufImag[n] = (float **) malloc( sizeof( float * ) * LCLD_PRED_WIN_LEN ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + for ( k = 0; k < LCLD_PRED_WIN_LEN; k++ ) + { + if ( ( psPredictionEncoder->pppfInpBufReal[n][k] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->pppfInpBufImag[n][k] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set_zero( psPredictionEncoder->pppfInpBufReal[n][k], LCLD_BANDS ); + set_zero( psPredictionEncoder->pppfInpBufImag[n][k], LCLD_BANDS ); + } + if ( ( psPredictionEncoder->ppfPredStateReal[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImag[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set_zero( psPredictionEncoder->ppfPredStateReal[n], LCLD_BANDS ); + set_zero( psPredictionEncoder->ppfPredStateImag[n], LCLD_BANDS ); + + if ( ( psPredictionEncoder->ppfInpPrevReal[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfInpPrevImag[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + + set_zero( psPredictionEncoder->ppfInpPrevReal[n], LCLD_BANDS ); + set_zero( psPredictionEncoder->ppfInpPrevImag[n], LCLD_BANDS ); + + if ( ( psPredictionEncoder->ppfPredStateRealTmp[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + if ( ( psPredictionEncoder->ppfPredStateImagTmp[n] = (float *) malloc( LCLD_BANDS * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD PredictionEncoder Module \n" ) ); + } + set_zero( psPredictionEncoder->ppfPredStateRealTmp[n], LCLD_BANDS ); + set_zero( psPredictionEncoder->ppfPredStateImagTmp[n], LCLD_BANDS ); + for ( k = 0; k < LCLD_BANDS; k++ ) + { + psPredictionEncoder->ppiPredBandEnable[n][k] = 0; + psPredictionEncoder->ppfA1Real[n][k] = 0.0f; + psPredictionEncoder->ppfA1Imag[n][k] = 0.0f; + } + } + + *psPredictionEncoder_out = psPredictionEncoder; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * Function DeletePredictionEncoder() + * + * + *-------------------------------------------------------------------*/ + +void DeletePredictionEncoder_fx( + PredictionEncoder *psPredictionEncoder ) +{ + Word32 n; + FOR( n = 0; n < psPredictionEncoder->iChannels; n++ ) + { + Word32 k; + free( psPredictionEncoder->ppiPredBandEnable[n] ); + free( psPredictionEncoder->ppfA1Real_fx[n] ); + free( psPredictionEncoder->ppfA1Imag_fx[n] ); + free( psPredictionEncoder->ppiA1Mag[n] ); + free( psPredictionEncoder->ppiA1Phase[n] ); + FOR( k = 0; k < LCLD_PRED_WIN_LEN; k++ ) + { + free( psPredictionEncoder->pppfInpBufReal_fx[n][k] ); + free( psPredictionEncoder->pppfInpBufImag_fx[n][k] ); + } + free( psPredictionEncoder->pppfInpBufReal_fx[n] ); + free( psPredictionEncoder->pppfInpBufImag_fx[n] ); + free( psPredictionEncoder->ppfInpPrevReal_fx[n] ); + free( psPredictionEncoder->ppfInpPrevImag_fx[n] ); + free( psPredictionEncoder->ppfPredStateReal_fx[n] ); + free( psPredictionEncoder->ppfPredStateImag_fx[n] ); + free( psPredictionEncoder->ppfPredStateRealTmp_fx[n] ); + free( psPredictionEncoder->ppfPredStateImagTmp_fx[n] ); + } + free( psPredictionEncoder->piPredChanEnable ); + free( psPredictionEncoder->piNumPredBands ); + free( psPredictionEncoder->ppiPredBandEnable ); + free( psPredictionEncoder->ppfA1Real_fx ); + free( psPredictionEncoder->ppfA1Imag_fx ); + free( psPredictionEncoder->ppiA1Mag ); + free( psPredictionEncoder->ppiA1Phase ); + free( psPredictionEncoder->pppfInpBufReal_fx ); + free( psPredictionEncoder->pppfInpBufImag_fx ); + free( psPredictionEncoder->ppfInpPrevReal_fx ); + free( psPredictionEncoder->ppfInpPrevImag_fx ); + free( psPredictionEncoder->ppfPredStateReal_fx ); + free( psPredictionEncoder->ppfPredStateImag_fx ); + free( psPredictionEncoder->ppfPredStateRealTmp_fx ); + free( psPredictionEncoder->ppfPredStateImagTmp_fx ); + + + free( psPredictionEncoder ); + + return; +} +void DeletePredictionEncoder( + PredictionEncoder *psPredictionEncoder ) +{ + int32_t n; + for ( n = 0; n < psPredictionEncoder->iChannels; n++ ) + { + int32_t k; + free( psPredictionEncoder->ppiPredBandEnable[n] ); + free( psPredictionEncoder->ppfA1Real[n] ); + free( psPredictionEncoder->ppfA1Imag[n] ); + free( psPredictionEncoder->ppiA1Mag[n] ); + free( psPredictionEncoder->ppiA1Phase[n] ); + for ( k = 0; k < LCLD_PRED_WIN_LEN; k++ ) + { + free( psPredictionEncoder->pppfInpBufReal[n][k] ); + free( psPredictionEncoder->pppfInpBufImag[n][k] ); + } + free( psPredictionEncoder->pppfInpBufReal[n] ); + free( psPredictionEncoder->pppfInpBufImag[n] ); + free( psPredictionEncoder->ppfInpPrevReal[n] ); + free( psPredictionEncoder->ppfInpPrevImag[n] ); + free( psPredictionEncoder->ppfPredStateReal[n] ); + free( psPredictionEncoder->ppfPredStateImag[n] ); + free( psPredictionEncoder->ppfPredStateRealTmp[n] ); + free( psPredictionEncoder->ppfPredStateImagTmp[n] ); + } + free( psPredictionEncoder->piPredChanEnable ); + free( psPredictionEncoder->piNumPredBands ); + free( psPredictionEncoder->ppiPredBandEnable ); + free( psPredictionEncoder->ppfA1Real ); + free( psPredictionEncoder->ppfA1Imag ); + free( psPredictionEncoder->ppiA1Mag ); + free( psPredictionEncoder->ppiA1Phase ); + free( psPredictionEncoder->pppfInpBufReal ); + free( psPredictionEncoder->pppfInpBufImag ); + free( psPredictionEncoder->ppfInpPrevReal ); + free( psPredictionEncoder->ppfInpPrevImag ); + free( psPredictionEncoder->ppfPredStateReal ); + free( psPredictionEncoder->ppfPredStateImag ); + free( psPredictionEncoder->ppfPredStateRealTmp ); + free( psPredictionEncoder->ppfPredStateImagTmp ); + + + free( psPredictionEncoder ); + + return; +} + + +/*-------------------------------------------------------------------* + * Function ComputePredictors() + * + * + *-------------------------------------------------------------------*/ + +void ComputePredictors( + PredictionEncoder *psPredictionEncoder, + float ***pppfReal, + float ***pppfImag ) +{ + int32_t c; + + int32_t b0 = psPredictionEncoder->iSubSetId; + int32_t bstep = psPredictionEncoder->iNumSubSets; + int32_t iNumBlocks = psPredictionEncoder->iNumBlocks; + float ***pppfRealBuf; + float ***pppfImagBuf; + float pfEstPredBitGain[LCLD_BANDS] = { 0 }; + + if ( iNumBlocks < LCLD_PRED_WIN_LEN ) + { + pppfRealBuf = psPredictionEncoder->pppfInpBufReal; + pppfImagBuf = psPredictionEncoder->pppfInpBufImag; + for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + int32_t n; + for ( n = 0; n < LCLD_PRED_WIN_LEN - iNumBlocks; n++ ) + { + mvr2r( pppfRealBuf[c][n + iNumBlocks], pppfRealBuf[c][n], LCLD_BANDS ); + mvr2r( pppfImagBuf[c][n + iNumBlocks], pppfImagBuf[c][n], LCLD_BANDS ); + } + for ( n = 0; n < iNumBlocks; n++ ) + { + mvr2r( pppfReal[c][n], pppfRealBuf[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS ); + mvr2r( pppfImag[c][n], pppfImagBuf[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS ); + } + } + } + else + { + pppfRealBuf = pppfReal; + pppfImagBuf = pppfImag; + } + + for ( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + int32_t b; + for ( b = b0; b < psPredictionEncoder->iMaxNumPredBands; b += bstep ) + { + int32_t n; + float fGain = 0.0; + float fBitGain = 0.0; + float *pfRxxReal; + float *pfRxxImag; + float fA1Real; + float fA1Imag; + int32_t iA1Mag; + int32_t iA1Phase; + + pfRxxReal = psPredictionEncoder->pfRxxReal; + pfRxxImag = psPredictionEncoder->pfRxxImag; + + pfRxxReal[0] = 0.0; + pfRxxImag[0] = 0.0; + for ( n = 0; n < LCLD_PRED_WIN_LEN; n++ ) + { + pfRxxReal[0] += ( pppfRealBuf[c][n][b] * pppfRealBuf[c][n][b] + pppfImagBuf[c][n][b] * pppfImagBuf[c][n][b] ); + } + + pfRxxReal[1] = 0.0; + pfRxxImag[1] = 0.0; + for ( n = 1; n < LCLD_PRED_WIN_LEN; n++ ) + { + pfRxxReal[1] += ( pppfRealBuf[c][n][b] * pppfRealBuf[c][n - 1][b] + pppfImagBuf[c][n][b] * pppfImagBuf[c][n - 1][b] ); + pfRxxImag[1] += ( pppfImagBuf[c][n][b] * pppfRealBuf[c][n - 1][b] - pppfRealBuf[c][n][b] * pppfImagBuf[c][n - 1][b] ); + } + + if ( pfRxxReal[0] > 1e-12f ) + { + float fA1Mag; + float fA1Phase; + float fGain2; + float fBitGain2; + int32_t iNumBlocksPerPredCoef = min( iNumBlocks * psPredictionEncoder->iNumSubSets, LCLD_PRED_WIN_LEN ); + + const float fMagScale = ( 2.0f * (float) ( 1 << ( PRED_QUNAT_FILTER_MAG_BITS ) ) + 1.0f ) / M_PI; + const float fInvMagScale = M_PI / ( 2.0f * (float) ( 1 << ( PRED_QUNAT_FILTER_MAG_BITS ) ) + 1.0f ); + const float fPhaseScale = (float) ( 1 << ( PRED_QUANT_FILTER_PHASE_BITS - 1 ) ) / M_PI; + const float fInvPhaseScale = M_PI / (float) ( 1 << ( PRED_QUANT_FILTER_PHASE_BITS - 1 ) ); + + /* Compute filter coefficeints */ + fA1Real = -pfRxxReal[1] / pfRxxReal[0]; + fA1Imag = -pfRxxImag[1] / pfRxxReal[0]; + + /* compute these before quant */ + /* Compute est coding gain based on quantized filter coefficients */ + fGain = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag ); + fBitGain = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS ); // Wrong fix (iNumBlocks-1) + fA1Mag = sqrtf( fA1Real * fA1Real + fA1Imag * fA1Imag ); + fA1Mag = fMagScale * asinf( fA1Mag ); + iA1Mag = (int32_t) ( fA1Mag + 0.5f ); + iA1Mag = ( iA1Mag > PRED_QUANT_FILTER_MAG_MIN ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MIN; + iA1Mag = ( iA1Mag < PRED_QUANT_FILTER_MAG_MAX ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MAX; + fA1Mag = sinf( fInvMagScale * (float) iA1Mag ); + + fA1Phase = atan2f( fA1Imag, fA1Real ); + fA1Phase = fPhaseScale * fA1Phase; + iA1Phase = ( fA1Phase > 0.0f ) ? (int32_t) ( fA1Phase + 0.5f ) : (int32_t) ( fA1Phase - 0.5f ); + iA1Phase = ( iA1Phase > PRED_QUANT_FILTER_PHASE_MIN ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MIN; + iA1Phase = ( iA1Phase < PRED_QUANT_FILTER_PHASE_MAX ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MAX; // Is this the correct way to deal with this? should wrap? + fA1Phase = fInvPhaseScale * (float) iA1Phase; + + fA1Real = fA1Mag * cosf( fA1Phase ); + fA1Imag = fA1Mag * sinf( fA1Phase ); + + fGain2 = 1.0f / ( 1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag ); + fBitGain2 = 0.65f * log2f( fGain ) * (float) ( iNumBlocksPerPredCoef ) - (float) ( PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS ); // Wrong fix (iNumBlocks-1) + fGain = ( fGain < fGain2 ) ? fGain : fGain2; + fBitGain = ( fBitGain < fBitGain2 ) ? fBitGain : fBitGain2; + } + else + { + fA1Real = 0.0f; + fA1Imag = 0.0f; + iA1Mag = 0; + iA1Phase = 0; + fGain = -10.0f; // Fix this + } + + pfEstPredBitGain[b] = fBitGain; + psPredictionEncoder->ppiPredBandEnable[c][b] = ( fBitGain > 0.0f ); // Initial prediction enable + psPredictionEncoder->ppfA1Real[c][b] = fA1Real; + psPredictionEncoder->ppfA1Imag[c][b] = fA1Imag; + psPredictionEncoder->ppiA1Mag[c][b] = iA1Mag; + psPredictionEncoder->ppiA1Phase[c][b] = iA1Phase; + } + + { + float fBestCost; + int32_t iPredBands; + float fBitGain; + int32_t iPredChanEnable = 0; + + fBestCost = 0.0; + iPredBands = 0; + fBitGain = -7.0; + for ( b = b0; b < psPredictionEncoder->iMaxNumPredBands; b += bstep ) + { // still getting this decision wrong! + fBitGain -= 1.0; + if ( psPredictionEncoder->ppiPredBandEnable[c][b] == 1 ) + { + fBitGain += pfEstPredBitGain[b]; + } + if ( fBitGain > fBestCost ) + { + fBestCost = fBitGain; + iPredBands = b; + iPredChanEnable = 1; + } + } + + if ( iPredChanEnable == 1 ) + { + for ( b = iPredBands + bstep; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = iPredBands + bstep; + } + else + { + for ( b = b0; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + deactivate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = 0; + } + } + } +} + +void ComputePredictors_fx( + PredictionEncoder *psPredictionEncoder, + Word32 ***pppfReal_fx, // Q12? + Word32 ***pppfImag_fx ) // Q12? +{ + Word32 c; + + Word32 b0 = psPredictionEncoder->iSubSetId; + Word32 bstep = psPredictionEncoder->iNumSubSets; + Word32 iNumBlocks = psPredictionEncoder->iNumBlocks; + /*float ***pppfRealBuf; + float ***pppfImagBuf;*/ + Word32 ***pppfRealBuf_fx; + Word32 ***pppfImagBuf_fx; + // float pfEstPredBitGain[LCLD_BANDS] = { 0 }; + Word32 pfEstPredBitGain_fx[LCLD_BANDS] = { 0 }; + + IF( LT_32( iNumBlocks, LCLD_PRED_WIN_LEN ) ) + { + /*pppfRealBuf = psPredictionEncoder->pppfInpBufReal; + pppfImagBuf = psPredictionEncoder->pppfInpBufImag;*/ + pppfRealBuf_fx = psPredictionEncoder->pppfInpBufReal_fx; + move32(); + pppfImagBuf_fx = psPredictionEncoder->pppfInpBufImag_fx; + move32(); + FOR( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + Word32 n; + FOR( n = 0; n < L_sub( LCLD_PRED_WIN_LEN, iNumBlocks ); n++ ) + { + /*mvr2r(pppfRealBuf[c][n + iNumBlocks], pppfRealBuf[c][n], LCLD_BANDS); + mvr2r(pppfImagBuf[c][n + iNumBlocks], pppfImagBuf[c][n], LCLD_BANDS);*/ + mvl2l( pppfRealBuf_fx[c][n + iNumBlocks], pppfRealBuf_fx[c][n], LCLD_BANDS ); + mvl2l( pppfImagBuf_fx[c][n + iNumBlocks], pppfImagBuf_fx[c][n], LCLD_BANDS ); + } + FOR( n = 0; n < iNumBlocks; n++ ) + { + /*mvr2r(pppfReal[c][n], pppfRealBuf[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS); + mvr2r(pppfImag[c][n], pppfImagBuf[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS);*/ + mvl2l( pppfReal_fx[c][n], pppfRealBuf_fx[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS ); + mvl2l( pppfImag_fx[c][n], pppfImagBuf_fx[c][n + LCLD_PRED_WIN_LEN - iNumBlocks], LCLD_BANDS ); + } + } + } + ELSE + { + /*pppfRealBuf = pppfReal; + pppfImagBuf = pppfImag;*/ + pppfRealBuf_fx = pppfReal_fx; + move32(); + pppfImagBuf_fx = pppfImag_fx; + move32(); + } + + FOR( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + Word32 b; + FOR( b = b0; b < psPredictionEncoder->iMaxNumPredBands; b += bstep ) + { + Word32 n; + /*float fGain = 0.0; + float fBitGain = 0.0; + float *pfRxxReal; + float *pfRxxImag; + float fA1Real; + float fA1Imag;*/ + Word32 fGain_fx = 0; + Word32 fBitGain_fx = 0; + Word32 *pfRxxReal_fx; + Word32 *pfRxxImag_fx; + Word32 fA1Real_fx; + Word32 fA1Imag_fx; + Word32 L_temp; + Word64 W_temp1, W_temp2; + Word32 iA1Mag; + Word32 iA1Phase; + + /*pfRxxReal = psPredictionEncoder->pfRxxReal; + pfRxxImag = psPredictionEncoder->pfRxxImag;*/ + pfRxxReal_fx = psPredictionEncoder->pfRxxReal_fx; + move32(); + pfRxxImag_fx = psPredictionEncoder->pfRxxImag_fx; + move32(); + /*pfRxxReal[0] = 0.0; + pfRxxImag[0] = 0.0;*/ + pfRxxReal_fx[0] = 0; + move32(); + pfRxxImag_fx[0] = 0; + move32(); + W_temp1 = 0; + FOR( n = 0; n < LCLD_PRED_WIN_LEN; n++ ) + { + // pfRxxReal[0] += (pppfRealBuf[c][n][b] * pppfRealBuf[c][n][b] + pppfImagBuf[c][n][b] * pppfImagBuf[c][n][b]); + W_temp1 = W_add( W_temp1, W_add( W_mult0_32_32( pppfRealBuf_fx[c][n][b], pppfRealBuf_fx[c][n][b] ), + W_mult0_32_32( pppfImagBuf_fx[c][n][b], pppfImagBuf_fx[c][n][b] ) ) ); // Q40 + } + Word16 w_norm1 = W_norm( W_temp1 ); + W_temp1 = W_shr( W_temp1, 32 - w_norm1 ); + pfRxxReal_fx[0] = W_extract_l( W_temp1 ); + /*pfRxxReal[1] = 0.0; + pfRxxImag[1] = 0.0;*/ + pfRxxReal_fx[1] = 0; + move32(); + pfRxxImag_fx[1] = 0; + move32(); + W_temp1 = 0; + W_temp2 = 0; + FOR( n = 1; n < LCLD_PRED_WIN_LEN; n++ ) + { + /*pfRxxReal[1] += (pppfRealBuf[c][n][b] * pppfRealBuf[c][n - 1][b] + pppfImagBuf[c][n][b] * pppfImagBuf[c][n - 1][b]); + pfRxxImag[1] += (pppfImagBuf[c][n][b] * pppfRealBuf[c][n - 1][b] - pppfRealBuf[c][n][b] * pppfImagBuf[c][n - 1][b]);*/ + W_temp1 = W_add( W_temp1, W_add( W_mult0_32_32( pppfRealBuf_fx[c][n][b], pppfRealBuf_fx[c][n - 1][b] ), + W_mult0_32_32( pppfImagBuf_fx[c][n][b], pppfImagBuf_fx[c][n - 1][b] ) ) ); // Q40 + W_temp2 = W_add( W_temp2, W_sub( W_mult0_32_32( pppfImagBuf_fx[c][n][b], pppfRealBuf_fx[c][n - 1][b] ), + W_mult0_32_32( pppfRealBuf_fx[c][n][b], pppfImagBuf_fx[c][n - 1][b] ) ) ); // Q40 + } + + Word16 w_norm2 = W_norm( W_temp1 ); + W_temp1 = W_shr( W_temp1, 32 - w_norm2 ); + pfRxxReal_fx[1] = W_extract_l( W_temp1 ); + Word16 w_norm3 = W_norm( W_temp2 ); + W_temp2 = W_shr( W_temp2, 32 - w_norm3 ); + pfRxxImag_fx[1] = W_extract_l( W_temp2 ); + Word16 final_w_norm = min( w_norm1, min( w_norm2, w_norm3 ) ); + pfRxxReal_fx[0] = L_shr( pfRxxReal_fx[0], w_norm1 - final_w_norm ); // Q8 + final_w_norm + pfRxxReal_fx[1] = L_shr( pfRxxReal_fx[1], w_norm2 - final_w_norm ); // Q8 + final_w_norm + pfRxxImag_fx[1] = L_shr( pfRxxImag_fx[1], w_norm3 - final_w_norm ); // Q8 + final_w_norm + // if (pfRxxReal[0] > 1e-12f) + IF( GT_32( pfRxxReal_fx[0], 0 ) ) + { + /*float fA1Mag; + float fA1Phase; + float fGain2; + float fBitGain2;*/ + Word32 fA1Mag_fx; + Word32 fA1Phase_fx; + Word32 fGain2_fx; + Word32 fBitGain2_fx; + Word32 iNumBlocksPerPredCoef = L_min( iNumBlocks * psPredictionEncoder->iNumSubSets, LCLD_PRED_WIN_LEN ); + const Word32 fMagScale_fx32 = 1452576210; // Q28 + move32(); + // const float fInvMagScale = M_PI / (2.0f * (float)(1 << (PRED_QUNAT_FILTER_MAG_BITS)) + 1.0f); + const Word16 fInvMagScale_fx = 6055; // Q15 + move16(); + // const float fPhaseScale = (float)(1 << (PRED_QUANT_FILTER_PHASE_BITS - 1)) / M_PI + const Word32 fPhaseScale_fx32 = 1367130551; // Q28 + // const float fInvPhaseScale = M_PI / (float)(1 << (PRED_QUANT_FILTER_PHASE_BITS - 1)); + const Word16 fInvPhaseScale_fx = 6434; // Q15 + move16(); + + /* Compute filter coefficeints */ + // fA1Real = -pfRxxReal[1] / pfRxxReal[0]; + Word16 sf_r, sf_i; + fA1Real_fx = BASOP_Util_Divide3232_Scale( -pfRxxReal_fx[1], pfRxxReal_fx[0], &sf_r ); + // fA1Imag = -pfRxxImag[1] / pfRxxReal[0]; + fA1Imag_fx = BASOP_Util_Divide3232_Scale( -pfRxxImag_fx[1], pfRxxReal_fx[0], &sf_i ); + + IF( GT_16( sf_r, sf_i ) ) + { + fA1Imag_fx = L_shr( fA1Imag_fx, sub( sf_r, sf_i ) ); + sf_i = sf_r; + move16(); + } + ELSE IF( LT_16( sf_r, sf_i ) ) + { + fA1Real_fx = L_shr( fA1Real_fx, sub( sf_i, sf_r ) ); + sf_r = sf_i; + move16(); + } + Word32 L_temp_1; + IF( LT_16( sf_r, -7 ) ) + { + fA1Real_fx = L_shr( fA1Real_fx, sub( -8, sf_r ) ); + fA1Imag_fx = L_shr( fA1Imag_fx, sub( -8, sf_i ) ); + sf_r = sf_i = -8; + move16(); + L_temp_1 = MAX_32; + move32(); + } + ELSE + { + L_temp_1 = L_shl( 1, sub( 15, shl( sf_r, 1 ) ) ); + } + /* compute these before quant */ + /* Compute est coding gain based on quantized filter coefficients */ + // fGain = 1.0f / (1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag); + L_temp = L_sub( L_sub( L_temp_1, mult_r( extract_l( fA1Real_fx ), extract_l( fA1Real_fx ) ) ), mult_r( extract_l( fA1Imag_fx ), extract_l( fA1Imag_fx ) ) ); + Word16 exp = norm_l( L_temp ); + IF( LT_16( exp, 16 ) ) + { + L_temp = L_shr( L_temp, sub( 16, exp ) ); + exp = add( sub( 16, exp ), shl( sf_r, 1 ) ); + } + else + { + exp = shl( sf_r, 1 ); + } + // fGain_fx = sub(sub(32767, extract_h(Mpy_32_32(fA1Real_fx, fA1Real_fx))), extract_h(Mpy_32_32(fA1Imag_fx, fA1Imag_fx))); + // fGain_fx = extract_l(L_shl(L_temp, 2*sf_r)); + fGain_fx = extract_l( L_temp ); + fGain_fx = max( 1, fGain_fx ); + fGain_fx = Inv16( extract_l( fGain_fx ), &exp ); // Q15 - exp + // fGain_fx = L_shl(fGain_fx, exp); //Q15 + // fBitGain = 0.65f * log2f(fGain) * (float)(iNumBlocksPerPredCoef)-(float)(PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS); // Wrong fix (iNumBlocks-1) + // fBitGain_fx = L_sub(L_mult0(L_shr(L_mult0(21299, L_shr(L_add(BASOP_Util_Log2(fGain_fx), 335544320), 10)), 15), (Word16)iNumBlocksPerPredCoef), 262144); // Wrong fix (iNumBlocks-1) Q15 + W_temp1 = W_mult0_32_32( L_shr( Mpy_32_32( 1395864371, L_add( BASOP_Util_Log2( fGain_fx ), L_shl( add( 16, exp ), 25 ) ) ), 10 ), iNumBlocksPerPredCoef ); + Word16 w_norm4 = W_norm( W_temp1 ); + IF( LT_16( w_norm4, 32 ) ) + { + W_temp1 = W_shr( W_temp1, 32 - w_norm4 ); + w_norm4 = sub( 32, w_norm4 ); + } + ELSE + { + w_norm4 = 0; + move16(); + } + fBitGain_fx = L_sub( W_extract_l( W_temp1 ), L_shr( 262144, w_norm4 ) ); // Wrong fix (iNumBlocks-1) Q15 + // fA1Mag = sqrtf(fA1Real * fA1Real + fA1Imag * fA1Imag); + fA1Mag_fx = L_add( mult_r( extract_l( fA1Real_fx ), extract_l( fA1Real_fx ) ), mult_r( extract_l( fA1Imag_fx ), extract_l( fA1Imag_fx ) ) ); // Q15 - 2*sf_r + // fA1Mag = fMagScale * asinf(fA1Mag); + exp = 0; + move16(); + L_temp = L_sub( L_temp_1, fA1Mag_fx ); // Q15 - 2*sf_r + IF( NE_32( L_temp, 0 ) ) + { + fA1Mag_fx = BASOP_Util_Divide3232_Scale( fA1Mag_fx, L_temp, &exp ); + } + ELSE + { + fA1Mag_fx = 0; + move32(); + exp = 0; + move16(); + } + fA1Mag_fx = L_shl( fA1Mag_fx, 16 ); + IF( fA1Mag_fx > 0 ) + { + fA1Mag_fx = Sqrt32( fA1Mag_fx, &exp ); + } + ELSE + { + fA1Mag_fx = 0; + move32(); + exp = 0; + move16(); + } + + fA1Mag_fx = BASOP_util_atan( L_shr_r_sat( fA1Mag_fx, 6 - exp ) ); // Q14 + fA1Mag_fx = Mpy_32_16_1( fMagScale_fx32, extract_l( fA1Mag_fx ) ); // Q27 + + // iA1Mag = (int32_t)(fA1Mag + 0.5f); + IF( GE_32( fA1Mag_fx, 0 ) ) + { + iA1Mag = L_shr( L_add( fA1Mag_fx, 67108864 ), Q27 ); // Q27 -> Q0 + } + ELSE + { + fA1Mag_fx = L_negate( fA1Mag_fx ); + iA1Mag = L_shr( L_add( fA1Mag_fx, 67108864 ), Q27 ); // Q27 -> Q0 + iA1Mag = L_negate( iA1Mag ); + } + iA1Mag = ( iA1Mag > PRED_QUANT_FILTER_MAG_MIN ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MIN; + iA1Mag = ( iA1Mag < PRED_QUANT_FILTER_MAG_MAX ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MAX; + // fA1Mag = sinf(fInvMagScale * (float)iA1Mag); + fA1Mag_fx = L_deposit_l( getSinWord16( extract_l( L_shr( L_mult0( extract_l( fInvMagScale_fx ), extract_l( iA1Mag ) ), 2 ) ) ) ); // Q14 + + // fA1Phase = atan2f(fA1Imag, fA1Real); + fA1Phase_fx = BASOP_util_atan2( fA1Imag_fx, fA1Real_fx, 0 ); // Q13 + // fA1Phase = fPhaseScale * fA1Phase; + fA1Phase_fx = Mpy_32_16_1( fPhaseScale_fx32, extract_l( fA1Phase_fx ) ); // Q26 + // iA1Phase = (fA1Phase > 0.0f) ? (int32_t)(fA1Phase + 0.5f) : (int32_t)(fA1Phase - 0.5f); + // iA1Phase = (fA1Phase_fx > 0) ? shr(add(fA1Phase_fx, 512), 10) : shr(sub(fA1Phase_fx, 512), 10); + IF( GE_32( fA1Phase_fx, 0 ) ) + { + iA1Phase = L_shr( L_add( fA1Phase_fx, 33554432 ), Q26 ); // Q26 -> Q0 + } + ELSE + { + fA1Phase_fx = L_negate( fA1Phase_fx ); + iA1Phase = L_shr( L_add( fA1Phase_fx, 33554432 ), Q26 ); // Q26 -> Q0 + iA1Phase = L_negate( iA1Phase ); + } + iA1Phase = ( iA1Phase > PRED_QUANT_FILTER_PHASE_MIN ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MIN; + iA1Phase = ( iA1Phase < PRED_QUANT_FILTER_PHASE_MAX ) ? iA1Phase : PRED_QUANT_FILTER_PHASE_MAX; // Is this the correct way to deal with this? should wrap? + // fA1Phase = fInvPhaseScale * (float)iA1Phase; + L_temp = L_mult0( fInvPhaseScale_fx, (Word16) iA1Phase ); // Q15 + + // fA1Real = fA1Mag * cosf(fA1Phase); + fA1Real_fx = L_mult0( extract_l( fA1Mag_fx ), getCosWord16( extract_l( L_shr( L_temp, 2 ) ) ) ); // Q28 + // fA1Imag = fA1Mag * sinf(fA1Phase); + fA1Imag_fx = L_mult0( extract_l( fA1Mag_fx ), getSinWord16( extract_l( L_shr( L_temp, 2 ) ) ) ); // Q28 + + // fGain2 = 1.0f / (1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag); + exp = 0; + fGain2_fx = sub( sub( 32767, mult_r( extract_l( L_shr( fA1Real_fx, 13 ) ), extract_l( L_shr( fA1Real_fx, 13 ) ) ) ), mult_r( extract_l( L_shr( fA1Imag_fx, 13 ) ), extract_l( L_shr( fA1Imag_fx, 13 ) ) ) ); + fGain2_fx = L_max( 1, fGain2_fx ); + fGain2_fx = Inv16( extract_l( fGain2_fx ), &exp ); // Q15-exp + fGain2_fx = L_shl( fGain2_fx, exp ); + // fBitGain2 = 0.65f * log2f(fGain) * (float)(iNumBlocksPerPredCoef)-(float)(PRED_QUNAT_FILTER_MAG_BITS + PRED_QUANT_FILTER_PHASE_BITS); // Wrong fix (iNumBlocks-1) + // fBitGain2_fx = L_sub(L_mult0(L_shr(L_mult0(21299, L_shr(L_add(BASOP_Util_Log2(fGain_fx), 335544320), 10)), 15), (Word16)iNumBlocksPerPredCoef), 262144); // Wrong fix (iNumBlocks-1) Q15 + fBitGain2_fx = L_sub( W_extract_l( W_temp1 ), L_shr( 262144, w_norm4 ) ); // Wrong fix (iNumBlocks-1) Q15 + // fGain = (fGain < fGain2) ? fGain : fGain2; + fGain_fx = ( fGain_fx < fGain2_fx ) ? fGain_fx : fGain2_fx; + // fBitGain = (fBitGain < fBitGain2) ? fBitGain : fBitGain2; + fBitGain_fx = ( fBitGain_fx < fBitGain2_fx ) ? fBitGain_fx : fBitGain2_fx; + } + ELSE + { + /*fA1Real = 0.0f; + fA1Imag = 0.0f;*/ + fA1Real_fx = 0; + move32(); + fA1Imag_fx = 0; + move32(); + iA1Mag = 0; + move32(); + iA1Phase = 0; + move32(); + // fGain = -10.0f; // Fix this + fGain_fx = -327680; // Fix this + move32(); + } + + // pfEstPredBitGain[b] = fBitGain; + // psPredictionEncoder->ppiPredBandEnable[c][b] = (fBitGain > 0.0f); // Initial prediction enable + // psPredictionEncoder->ppfA1Real[c][b] = fA1Real; + // psPredictionEncoder->ppfA1Imag[c][b] = fA1Imag; + pfEstPredBitGain_fx[b] = fBitGain_fx; // Q15 + move32(); + // printf("\n %d %d %f %f %f ", iA1Mag, iA1Phase, (float)fBitGain_fx / 32768, (float)fA1Real_fx / ONE_IN_Q28, (float)fA1Imag_fx / ONE_IN_Q28); + psPredictionEncoder->ppiPredBandEnable[c][b] = ( fBitGain_fx > 0 ); // Initial prediction enable + psPredictionEncoder->ppfA1Real_fx[c][b] = L_shl( fA1Real_fx, Q3 ); // Q31 + psPredictionEncoder->ppfA1Imag_fx[c][b] = L_shl( fA1Imag_fx, Q3 ); // Q31 + psPredictionEncoder->ppiA1Mag[c][b] = iA1Mag; + move32(); + psPredictionEncoder->ppiA1Phase[c][b] = iA1Phase; + move32(); + } + + { + // float fBestCost; + Word32 fBestCost_fx; + Word32 iPredBands; + // float fBitGain; + Word32 fBitGain_fx; + Word32 iPredChanEnable = 0; + + // fBestCost = 0.0; + fBestCost_fx = 0; + move32(); + iPredBands = 0; + move32(); + // fBitGain = -7.0; + fBitGain_fx = -229376; // Q15 + move32(); + FOR( b = b0; b < psPredictionEncoder->iMaxNumPredBands; b += bstep ) + { // still getting this decision wrong! + // fBitGain -= 1.0; + fBitGain_fx = L_sub( fBitGain_fx, 32768 ); + IF( EQ_32( psPredictionEncoder->ppiPredBandEnable[c][b], 1 ) ) + { + // fBitGain += pfEstPredBitGain[b]; + fBitGain_fx = L_add( fBitGain_fx, pfEstPredBitGain_fx[b] ); + } + // if (fBitGain > fBestCost) + IF( GT_32( fBitGain_fx, fBestCost_fx ) ) + { + fBestCost_fx = fBitGain_fx; + iPredBands = b; + iPredChanEnable = 1; + } + } + + IF( EQ_32( iPredChanEnable, 1 ) ) + { + FOR( b = iPredBands + bstep; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + activate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = iPredBands + bstep; + } + ELSE + { + FOR( b = b0; b < LCLD_BANDS; b += bstep ) + { + psPredictionEncoder->ppiPredBandEnable[c][b] = 0; + } + deactivate_bit( &psPredictionEncoder->piPredChanEnable[c], psPredictionEncoder->iSubSetId ); + psPredictionEncoder->piNumPredBands[c] = 0; + move32(); + } + } + } +} + +/*-------------------------------------------------------------------* + * Function ApplyForwardPredictors() + * + * + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * Function WritePredictors() + * + * + *-------------------------------------------------------------------*/ + +Word32 WritePredictors( + PredictionEncoder *psPredictionEncoder, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsWritten = 0; + Word32 c; + Word32 iNumSubSets = psPredictionEncoder->iNumSubSets; + Word32 iSubSetId = psPredictionEncoder->iSubSetId; + Word32 iNumPredBandBits = 6; + const Word16 iSubSetBits = ( GT_16( LCLD_MAX_NUM_PRED_SUBSETS, 4 ) ? 3 : 2 ); + move32(); + move32(); + move16(); + + /* number of subsets */ + ISAR_SPLIT_REND_BITStream_write_int32( pBits, L_sub( iNumSubSets, 1 ), iSubSetBits ); /* otherwise use default */ + iBitsWritten = L_add( iBitsWritten, iSubSetBits ); + + IF( GT_32( iNumSubSets, 1 ) ) + { + /* write current subset */ + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iSubSetId, iSubSetBits ); + iBitsWritten = L_add( iBitsWritten, iSubSetBits ); + iNumPredBandBits = ( GE_32( iNumSubSets, 4 ) ? 4 : 5 ); + move32(); + } + + FOR( c = 0; c < psPredictionEncoder->iChannels; c++ ) + { + Word32 b; + Word32 b0 = iSubSetId; + move32(); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, psPredictionEncoder->piPredChanEnable[c], iNumSubSets ); + iBitsWritten = L_add( iBitsWritten, iNumSubSets ); + + IF( get_bit( psPredictionEncoder->piPredChanEnable[c], iSubSetId ) ) + { + Word32 iNumPredBands = L_sub( psPredictionEncoder->piNumPredBands[c], b0 ) / iNumSubSets; + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iNumPredBands, iNumPredBandBits ); + iBitsWritten = L_add( iBitsWritten, iNumPredBandBits ); + + FOR( b = b0; b < psPredictionEncoder->piNumPredBands[c]; b += iNumSubSets ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, psPredictionEncoder->ppiPredBandEnable[c][b], 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + + IF( EQ_32( psPredictionEncoder->ppiPredBandEnable[c][b], 1 ) ) + { + Word32 iA1Mag; + Word32 iA1Phase; + + iA1Mag = psPredictionEncoder->ppiA1Mag[c][b]; + move32(); + iA1Phase = L_sub( psPredictionEncoder->ppiA1Phase[c][b], PRED_QUANT_FILTER_PHASE_MIN ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iA1Mag, PRED_QUNAT_FILTER_MAG_BITS ); + iBitsWritten = L_add( iBitsWritten, PRED_QUNAT_FILTER_MAG_BITS ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iA1Phase, PRED_QUANT_FILTER_PHASE_BITS ); + iBitsWritten = L_add( iBitsWritten, PRED_QUANT_FILTER_PHASE_BITS ); + } + } + } + } + + return iBitsWritten; +} +#endif diff --git a/lib_isar/isar_RMSEnvGrouping.c b/lib_isar/isar_RMSEnvGrouping.c new file mode 100644 index 000000000..0c24040be --- /dev/null +++ b/lib_isar/isar_RMSEnvGrouping.c @@ -0,0 +1,964 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +/* Double check cost function calculation */ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "prot.h" +#include "isar_lcld_prot.h" +#include "isar_lcld_rom_tables.h" +#include "wmc_auto.h" +#include "prot_fx2.h" +#include "basop_util.h" +#include "enh64.h" +Word32 Inv_grp_length[17] = { + // Q31 + 0, + 2147483647, + 1073741823, + 715827882, + 536870911, + 429496729, + 357913941, + 306783378, + 268435455, + 238609294, + 214748364, + 195225786, + 178956970, + 165191049, + 153391689, + 143165576, + 134217727, + +}; + +/*-------------------------------------------------------------------* + * Local ROM tables + * + * + *-------------------------------------------------------------------*/ +static const Word32 c_afThreshQuiet48_fx[23] = { + // Q23 + -705191424, + -705191424, + -705191424, + -705191424, + -705191424, + -705191424, + -705191424, + -705191424, + -703021824, + -694920256, + -685375488, + -662531840, + -646432768, + -636262784, + -627448000, + -618652544, + -598245120, + -575579520, + -550540736, + -508787360, + -264583456, + -161516096, + -158042848, +}; +static const Word32 c_fiDefaultTheta48_fx[MAX_BANDS_48] = { + // Q31 + 939524096, + 939524096, + 805306368, + 671088640, + 671088640, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, + 536870912, +}; +typedef struct GMNODE +{ + int32_t iGroupStart; + int32_t iGroupLength; + Word32 *pfMergedEnergydB_fx; + int32_t *piQRMSEnvelope; + + int32_t iGroupRMSEnvelopeCost; + Word32 fGroupSNRPenalty_fx; + Word16 fGroupSNRPenalty_exp; + struct GMNODE *psNext; +} GMNode; + +struct RMS_ENVELOPE_GROUPING +{ + int32_t iNumBlocks; + int32_t iMaxGroups; + Word32 **ppfWeight_man; + Word16 **ppfWeight_exp; + Word32 **ppfBandEnergy_man; + Word16 **ppfBandEnergy_exp; + Word32 **ppfBandEnergydB_fx; + // Word32 **ppfWeight_fx; + GMNode *psGMNodes; +}; + + +/*-------------------------------------------------------------------* + * Function CreateRMSEnvelopeGrouping() + * + * + *-------------------------------------------------------------------*/ + +RMSEnvelopeGrouping *CreateRMSEnvelopeGrouping( + const Word32 iNumBlocks ) +{ + Word32 n; + + RMSEnvelopeGrouping *psRMSEnvelopeGrouping; + + psRMSEnvelopeGrouping = (RMSEnvelopeGrouping *) malloc( sizeof( RMSEnvelopeGrouping ) ); + psRMSEnvelopeGrouping->iNumBlocks = iNumBlocks; + + psRMSEnvelopeGrouping->iMaxGroups = iNumBlocks >> 1; + psRMSEnvelopeGrouping->ppfBandEnergy_man = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) ); + psRMSEnvelopeGrouping->ppfBandEnergy_exp = (Word16 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word16 * ) ); + psRMSEnvelopeGrouping->ppfBandEnergydB_fx = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) ); + psRMSEnvelopeGrouping->ppfWeight_man = (Word32 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word32 * ) ); + psRMSEnvelopeGrouping->ppfWeight_exp = (Word16 **) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( Word16 * ) ); + + for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ ) + { + psRMSEnvelopeGrouping->ppfBandEnergy_man[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) ); /* 2 for stereo joint group calc */ + psRMSEnvelopeGrouping->ppfBandEnergy_exp[n] = (Word16 *) malloc( MAX_BANDS * 2 * sizeof( Word16 ) ); /* 2 for stereo joint group calc */ + psRMSEnvelopeGrouping->ppfBandEnergydB_fx[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) ); + psRMSEnvelopeGrouping->ppfWeight_man[n] = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( Word32 ) ); + psRMSEnvelopeGrouping->ppfWeight_exp[n] = (Word16 *) malloc( MAX_BANDS * 2 * sizeof( Word16 ) ); + } + + psRMSEnvelopeGrouping->psGMNodes = (GMNode *) malloc( psRMSEnvelopeGrouping->iNumBlocks * sizeof( GMNode ) ); + for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ ) + { + psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB_fx = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( float ) ); + psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope = (Word32 *) malloc( MAX_BANDS * 2 * sizeof( int32_t ) ); + psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1; + psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 ); + psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_exp = 1; + } + + return psRMSEnvelopeGrouping; +} + + +/*-------------------------------------------------------------------* + * Function DeleteRMSEnvelopeGrouping() + * + * + *-------------------------------------------------------------------*/ + +void DeleteRMSEnvelopeGrouping( + RMSEnvelopeGrouping *psRMSEnvelopeGrouping ) +{ + int32_t n; + + for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ ) + { + free( psRMSEnvelopeGrouping->ppfBandEnergy_man[n] ); + free( psRMSEnvelopeGrouping->ppfBandEnergy_exp[n] ); + free( psRMSEnvelopeGrouping->ppfBandEnergydB_fx[n] ); + free( psRMSEnvelopeGrouping->ppfWeight_man[n] ); + free( psRMSEnvelopeGrouping->ppfWeight_exp[n] ); + } + free( psRMSEnvelopeGrouping->ppfBandEnergy_man ); + free( psRMSEnvelopeGrouping->ppfBandEnergy_exp ); + free( psRMSEnvelopeGrouping->ppfBandEnergydB_fx ); + free( psRMSEnvelopeGrouping->ppfWeight_man ); + free( psRMSEnvelopeGrouping->ppfWeight_exp ); + + + for ( n = 0; n < psRMSEnvelopeGrouping->iNumBlocks; n++ ) + { + free( psRMSEnvelopeGrouping->psGMNodes[n].pfMergedEnergydB_fx ); + free( psRMSEnvelopeGrouping->psGMNodes[n].piQRMSEnvelope ); + } + free( psRMSEnvelopeGrouping->psGMNodes ); + + free( psRMSEnvelopeGrouping ); + + return; +} + + +/*-------------------------------------------------------------------* + * Function ComputeBandEnergy() + * + * + *-------------------------------------------------------------------*/ +static void ComputeBandEnergy( + const Word32 iChannels, + const Word32 iNumBlocks, + const Word32 iNumBands, + const Word32 *piBandwidths, + Word32 ***pppfReal_fx, + Word32 ***pppfImag_fx, + Word32 **ppfBandEnergy_man, + Word16 **ppfBandEnergy_exp, + Word32 **ppfBandEnergydB_fx, + Word32 **ppfWeight_man, + Word16 **ppfWeight_exp, + Word16 q_final ) +{ + + Word32 n; + Word32 constant = 1616142483; // Q29 of(1/log2(10))*10 + Word32 const_comp3, const_comp1; + Word16 exp3 = 0, exp1 = 0, Flag1, Flag2, Flag3; + Word16 div_exp; + /*For 0.33f*/ + const_comp3 = 1417339264; + move32(); + exp3 = -1; + move16(); + // f2me( 0.33, &const_comp3, &exp3 );// + // f2me( 1.0, &const_comp1, &exp1 );// + /*For 1.0f*/ + Word32 mul_32; + Word16 mul_exp; + const_comp1 = 1073741824; + move32(); + exp1 = 1; + move16(); + FOR( n = 0; n < iChannels; n++ ) + { + Word32 k; + Word32 iChanOffset; + + iChanOffset = L_mult0( extract_l( n ), extract_l( iNumBands ) ); + FOR( k = 0; k < iNumBlocks; k++ ) + { + Word32 b; + Word32 iFBOffset; + Word32 fMaxWeight_fx = 0; + move32(); + Word16 fMaxWeight_exp = 0; + move16(); + iFBOffset = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 m; + Word16 fEnergy_exp; + Word32 fEnergy_fx, fWeight_temp; + Word16 shift_value; + Word32 fEnergy_log_fx, fEnergy_log_fx1; + fEnergy_exp = 0; + move16(); + /*For 1e-12f in Q63*/ + Word32 fWeight_fx; + Word64 Wmult_value; + Word16 exp_pow = 0; + move16(); + Word16 guard_bits = find_guarded_bits_fx( piBandwidths[b] + 1 ); + // fEnergy_f64 = W_shr( fEnergy_f64, ( 63 - ( 2 * ( q_final - guard_bits ) + 1 ) ) ); + fEnergy_fx = 1180591616; + fEnergy_exp = -39; + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + Wmult_value = W_add( W_mult_32_32( L_shr( pppfReal_fx[n][k][iFBOffset], guard_bits ), L_shr( pppfReal_fx[n][k][iFBOffset], guard_bits ) ), W_mult_32_32( L_shr( pppfImag_fx[n][k][iFBOffset], guard_bits ), L_shr( pppfImag_fx[n][k][iFBOffset], guard_bits ) ) ); + shift_value = W_norm( Wmult_value ); + mul_32 = W_extract_h( W_shl( Wmult_value, shift_value ) ); + mul_exp = 31 - ( 2 * ( q_final - guard_bits ) + 1 + shift_value - 32 ); + fEnergy_fx = BASOP_Util_Add_Mant32Exp( fEnergy_fx, fEnergy_exp, mul_32, mul_exp, &fEnergy_exp ); // Some large number to prevent clipping + iFBOffset++; + } + IF( EQ_32( fEnergy_fx, 0 ) ) + { + // f2me( 1e-12f, &fEnergy_fx, &fEnergy_exp ); // + fEnergy_fx = 1180591616; + fEnergy_exp = -39; + fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2 + ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx; + move32(); + ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp; + move16(); + fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2 + ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx; + move32(); + ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp; + move16(); + fEnergy_log_fx1 = -1006632960; // Q23 + fWeight_fx = 403727488; // Q31 + exp_pow = 0; + } + ELSE + { + fEnergy_fx = Mpy_32_32( fEnergy_fx, Inv_grp_length[piBandwidths[b]] ); // Correction removed normalization by 2 + ppfBandEnergy_man[k][iChanOffset + b] = fEnergy_fx; + move32(); + ppfBandEnergy_exp[k][iChanOffset + b] = fEnergy_exp; + move16(); + fEnergy_fx = BASOP_Util_Log2( fEnergy_fx ); + move32(); + fEnergy_log_fx = L_add( fEnergy_fx, L_shl( L_deposit_l( fEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ // log2f( fEnergy ) + fEnergy_log_fx1 = Mpy_32_32( fEnergy_log_fx, constant ); + fEnergy_log_fx = L_sub( fEnergy_log_fx1, c_afThreshQuiet48_fx[b] ); // Q23 of ( 10.0f * log10f( fEnergy ) - c_afThreshQuiet48[b] ) ) + fWeight_fx = Mpy_32_32( 48509336, fEnergy_log_fx ); // 0.0068f*3.3219 in Q31, result in Q23 + fWeight_temp = BASOP_util_Pow2( fWeight_fx, 8, &exp_pow ); + fWeight_fx = Mpy_32_32( 708669604, fWeight_temp ); // 708669604 = Q31 0f 0.33 + } + Flag1 = BASOP_Util_Cmp_Mant32Exp( fWeight_fx, exp_pow, const_comp3, exp3 ); + IF( NE_16( Flag1, 1 ) ) + { + fWeight_fx = const_comp3; + move32(); + exp_pow = exp3; + move16(); + } + Flag2 = BASOP_Util_Cmp_Mant32Exp( const_comp1, exp1, fWeight_fx, exp_pow ); + IF( NE_16( Flag2, 1 ) ) + { + fWeight_fx = const_comp1; + move32(); + exp_pow = exp1; + move16(); + } + Flag3 = BASOP_Util_Cmp_Mant32Exp( fMaxWeight_fx, fMaxWeight_exp, fWeight_fx, exp_pow ); + IF( NE_16( Flag3, 1 ) ) + { + fMaxWeight_fx = fWeight_fx; + move32(); + fMaxWeight_exp = exp_pow; + move16(); + } +#ifdef APPLY_TEMPORAL_SMOOTHING + if ( k > 0 ) + { + float fSmoothEnergy; + fSmoothEnergy = 0.7f * ppfBandEnergy[k - 1][iChanOffset + b] + 0.3f * fEnergy; + + fEnergy = ( fEnergy > fSmoothEnergy ) ? fEnergy : fSmoothEnergy; + } +#endif + ppfWeight_man[k][iChanOffset + b] = fWeight_fx; + ppfWeight_exp[k][iChanOffset + b] = exp_pow; + ppfBandEnergydB_fx[k][iChanOffset + b] = fEnergy_log_fx1; // Q23 + } + FOR( b = 0; b < iNumBands; b++ ) + { + ppfWeight_man[k][iChanOffset + b] = L_deposit_h( BASOP_Util_Divide3232_Scale( ppfWeight_man[k][iChanOffset + b], fMaxWeight_fx, &div_exp ) ); + ppfWeight_exp[k][iChanOffset + b] = div_exp + ppfWeight_exp[k][iChanOffset + b] - fMaxWeight_exp; + } + } + } + /* fclose( fp ); + fclose( fp1 );*/ + return; +} +/*-------------------------------------------------------------------* + * Function ComputeMergeRMS() + * + * + *-------------------------------------------------------------------*/ +static void ComputeMergeRMS( + const Word32 iNumBands, + const Word32 iStartBlock, + const Word32 iGroupLength, + Word32 *pfMergedEnergydB, + Word32 *piQRMSEnvelope, + Word32 **ppfBandEnergy_man, + Word16 **ppfBandEnergy_exp ) +{ + Word32 b; + /* FILE *fp = fopen( "float_fGroupEnergy.txt","ab+" ); + FILE *fp1 = fopen( "fixed_fGroupEnergy.txt","ab+" );*/ + Word32 constant = 1616142483; // Q29 of(1/log2(10))*10 // Note epsolon was added when computing BandEnergy; + move32(); + Word32 fGroupEnergy32_fx; + + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 n; + Word32 fGroupEnergy_fx = 0; + move32(); + Word16 fGroupEnergy_exp = 0; + move16(); + Word32 fRMSEnvelope_fx; + Word32 iQRMSEnvelope_fx; + FOR( n = iStartBlock; n < ( iStartBlock + iGroupLength ); n++ ) + { + fGroupEnergy_fx = BASOP_Util_Add_Mant32Exp( ppfBandEnergy_man[n][b], ppfBandEnergy_exp[n][b], fGroupEnergy_fx, fGroupEnergy_exp, &fGroupEnergy_exp ); + } + fGroupEnergy_fx = Mpy_32_32( fGroupEnergy_fx, Inv_grp_length[iGroupLength] ); // Division by iGroupLength + move32(); + IF( NE_32( fGroupEnergy_fx, 0 ) ) + { + fRMSEnvelope_fx = BASOP_Util_Log2( fGroupEnergy_fx ); + move32(); + fRMSEnvelope_fx = L_add( fRMSEnvelope_fx, L_shl( L_deposit_l( fGroupEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ + } + ELSE + { + fRMSEnvelope_fx = 0; + fGroupEnergy_exp = 0; + } + iQRMSEnvelope_fx = ( fRMSEnvelope_fx > 0 ) ? L_add( fRMSEnvelope_fx, ONE_IN_Q24 ) : L_negate( L_add( L_negate( fRMSEnvelope_fx ), ONE_IN_Q24 ) ); + iQRMSEnvelope_fx = L_shr( iQRMSEnvelope_fx, 25 ); + + fGroupEnergy32_fx = fRMSEnvelope_fx; /*Q25*/ // BASOP_Util_Log2( fGroupEnergy_fx ); + fGroupEnergy32_fx = Mpy_32_32( fGroupEnergy32_fx, constant ); // Q23 + pfMergedEnergydB[b] = fGroupEnergy32_fx; // Q23 + piQRMSEnvelope[b] = iQRMSEnvelope_fx; // Q25 + } + return; +} +/*-------------------------------------------------------------------* + * Function ComputeRMSEnvelopeBits() + * + * + *-------------------------------------------------------------------*/ +static Word32 ComputeRMSEnvelopeBits( + const Word32 iChannels, + const Word32 iNumBands, + const Word32 *piQRMSEnevelope ) +{ + Word32 n; + Word32 iRMSEnvelopeBits = 0; + move32(); + Word32 iChanOffset = 0; + move32(); + + FOR( n = 0; n < iChannels; n++ ) + { + Word32 b; + Word32 iLastRMSVal; + + iRMSEnvelopeBits = L_add( iRMSEnvelopeBits, ENV0_BITS ); + iLastRMSVal = piQRMSEnevelope[iChanOffset]; + move32(); + FOR( b = 1; b < iNumBands; b++ ) + { + Word32 iDelta; + + iDelta = L_sub( piQRMSEnevelope[iChanOffset + b], iLastRMSVal ); + iDelta = ( iDelta > ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN; + iDelta = ( iDelta < ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX; + iDelta = L_sub( iDelta, ENV_DELTA_MIN ); + iRMSEnvelopeBits = L_add( iRMSEnvelopeBits, c_aaiRMSEnvHuffEnc[iDelta][0] ); + + iLastRMSVal = piQRMSEnevelope[iChanOffset + b]; + move32(); + } + + iChanOffset = L_add( iChanOffset, iNumBands ); + } + + return iRMSEnvelopeBits; +} +/*-------------------------------------------------------------------* + * Function ComputeSNRPenalty() + * + * + *-------------------------------------------------------------------*/ +static Word32 ComputeSNRPenalty( + const Word32 iChannels, + const Word32 iNumBands, + const Word32 *piBandwidths, + const Word32 iStartBlock, + const Word32 iGroupLength, + Word32 **ppfBandEnergy_dB_fx, + const Word32 *piRMSEnvelope, + Word16 *fSNRPenalty_exp ) +{ + Word32 n; + Word32 iChanOffset; + Word32 temp; + Word32 fSNRPenalty_fx = 0; + move32(); + Word32 fSNRPenaltyconst_fx = 0; + move32(); + Word32 mul_temp; + Word16 fSNRPenaltycnst_exp = 0, exp = 0; + /*FILE *fp = fopen( "float_SNRpenalty.txt", "ab+" ); + FILE *fp1 = fopen( "fixed_SNRpenalty.txt", "ab+" );*/ + // f2me( 1e10f, &fSNRPenaltyconst_fx, &fSNRPenaltycnst_exp );// + /*For 1e10f*/ + fSNRPenaltyconst_fx = 1250000000; + fSNRPenaltycnst_exp = 34; + iChanOffset = 0; + move32(); + FOR( n = 0; n < iChannels; n++ ) + { + Word32 b; + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 k; + Word32 fRMSVal_fx; + Word32 RMS_value_fx; + // RMS_value = piRMSEnvelope[iChanOffset + b]; + RMS_value_fx = L_shl( piRMSEnvelope[iChanOffset + b], 25 ); + move32(); + // fRMSVal = 3.0103f * (float) RMS_value; + fRMSVal_fx = Mpy_32_32( 1616142506, RMS_value_fx ); // Q23 + move32(); + FOR( k = iStartBlock; k < ( iStartBlock + iGroupLength ); k++ ) + { + Word32 fDeltadB_fx; + fDeltadB_fx = L_sub( fRMSVal_fx, ppfBandEnergy_dB_fx[k][iChanOffset + b] ); + IF( LT_32( fDeltadB_fx, -75756680 ) ) + { + fSNRPenalty_fx = BASOP_Util_Add_Mant32Exp( fSNRPenalty_fx, *fSNRPenalty_exp, fSNRPenaltyconst_fx, fSNRPenaltycnst_exp, fSNRPenalty_exp ); // Some large number to prevent clipping + } + ELSE + { + mul_temp = L_abs( L_sub( Mpy_32_32( c_fiDefaultTheta48_fx[b], fDeltadB_fx ), fDeltadB_fx ) ); + temp = Mpy_32_32( mul_temp, Mpy_32_32( 715827883, L_shl( piBandwidths[b], 27 ) ) ); // Q27+23 -31=19 + exp = Q12; // Q31 - Q19 + fSNRPenalty_fx = BASOP_Util_Add_Mant32Exp( fSNRPenalty_fx, *fSNRPenalty_exp, temp, exp, fSNRPenalty_exp ); + } + } + } + + iChanOffset = L_add( iChanOffset, iNumBands ); + } + // fprintf( fp,"%f\n", fSNRPenalty ); + // fprintf( fp1,"%f\n", fSNRPenalty ); + /* fclose( fp ); + fclose( fp1 );*/ + return fSNRPenalty_fx; +} +/*-------------------------------------------------------------------* + * Function TryMerge2() + * + * + *-------------------------------------------------------------------*/ +static Word32 TryMerge2( + const Word32 iChannels, + const Word32 iNumBands, + const Word32 *piBandwidths, + Word32 **ppfBandEnergy_man, + Word16 **ppfBandEnergy_exp, + Word32 **ppfBandEnergydB_fx, + GMNode *psGMNode1, + GMNode *psGMNode2, + Word16 *fMergedCost_exp ) +{ + Word32 iRMSEnvBits1; + Word32 iRMSEnvBits2; + Word32 iRMSEnvBitsMerged; + Word32 temp = 0; + move32(); + Word16 temp_exp = 0; + move16(); + Word32 fMergedCost_fx = 0; + move32(); + Word32 RMSEnvBits_fx; + Word32 fSNRPenalty1_fx; + Word32 fSNRPenalty2_fx; + Word32 fSNRPenaltyMerged_fx; + Word16 fSNRPenalty1_exp = 0; + move16(); + Word16 fSNRPenalty2_exp = 0; + move16(); + Word16 fSNRPenaltyMerged_exp = 0; + move16(); + Word32 one_in_mant = L_negate( ONE_IN_Q30 ); + Word16 one_in_exp = 1; + move16(); + *fMergedCost_exp = 0; + move16(); + Word16 flag = 0; + move16(); + IF( EQ_32( psGMNode1->fGroupSNRPenalty_fx, one_in_mant ) && EQ_16( psGMNode1->fGroupSNRPenalty_exp, one_in_exp ) ) + { + flag = 1; + move16(); + } + /* First compute current RMS Envelope for each group */ + IF( EQ_32( psGMNode1->iGroupRMSEnvelopeCost, -1 ) || flag ) + { + ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength, psGMNode1->pfMergedEnergydB_fx, psGMNode1->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp ); + iRMSEnvBits1 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope ); + fSNRPenalty1_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength, ppfBandEnergydB_fx, psGMNode1->piQRMSEnvelope, &fSNRPenalty1_exp ); + psGMNode1->iGroupRMSEnvelopeCost = iRMSEnvBits1; + move32(); + psGMNode1->fGroupSNRPenalty_fx = fSNRPenalty1_fx; + move32(); + psGMNode1->fGroupSNRPenalty_exp = fSNRPenalty1_exp; + move16(); + } + ELSE + { + iRMSEnvBits1 = psGMNode1->iGroupRMSEnvelopeCost; + move32(); + fSNRPenalty1_fx = psGMNode1->fGroupSNRPenalty_fx; + move32(); + fSNRPenalty1_exp = psGMNode1->fGroupSNRPenalty_exp; + move16(); + } + IF( EQ_32( psGMNode2->fGroupSNRPenalty_fx, one_in_mant ) && EQ_16( psGMNode2->fGroupSNRPenalty_exp, one_in_exp ) ) + { + flag = 1; + move16(); + } + IF( EQ_32( psGMNode2->iGroupRMSEnvelopeCost, -1 ) || flag ) + { + + ComputeMergeRMS( iNumBands * iChannels, psGMNode2->iGroupStart, psGMNode2->iGroupLength, psGMNode2->pfMergedEnergydB_fx, psGMNode2->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp ); + iRMSEnvBits2 = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode2->piQRMSEnvelope ); + fSNRPenalty2_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode2->iGroupStart, psGMNode2->iGroupLength, ppfBandEnergydB_fx, psGMNode2->piQRMSEnvelope, &fSNRPenalty2_exp ); + psGMNode2->iGroupRMSEnvelopeCost = iRMSEnvBits2; + move32(); + psGMNode2->fGroupSNRPenalty_fx = fSNRPenalty2_fx; + move32(); + psGMNode2->fGroupSNRPenalty_exp = fSNRPenalty2_exp; + move16(); + } + ELSE + { + iRMSEnvBits2 = psGMNode2->iGroupRMSEnvelopeCost; + move32(); + fSNRPenalty2_fx = psGMNode2->fGroupSNRPenalty_fx; + move32(); + fSNRPenalty2_exp = psGMNode2->fGroupSNRPenalty_exp; + move16(); + } + ComputeMergeRMS( iNumBands * iChannels, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, psGMNode1->pfMergedEnergydB_fx, psGMNode1->piQRMSEnvelope, ppfBandEnergy_man, ppfBandEnergy_exp ); + + /* Compute the RMS Envelope cost for merged group */ + iRMSEnvBitsMerged = ComputeRMSEnvelopeBits( iChannels, iNumBands, psGMNode1->piQRMSEnvelope ); + // fSNRPenalty_exp = 0; + /* Compute an approximation of the bit cost based on SNR increase/decrease due to merging */ + fSNRPenaltyMerged_fx = ComputeSNRPenalty( iChannels, iNumBands, piBandwidths, psGMNode1->iGroupStart, psGMNode1->iGroupLength + psGMNode2->iGroupLength, ppfBandEnergydB_fx, psGMNode1->piQRMSEnvelope, &fSNRPenaltyMerged_exp ); + RMSEnvBits_fx = L_sub( L_sub( iRMSEnvBitsMerged, iRMSEnvBits1 ), iRMSEnvBits2 ); + RMSEnvBits_fx = L_shl( RMSEnvBits_fx, 10 ); // Converting to Q10 + temp = BASOP_Util_Add_Mant32Exp( fSNRPenaltyMerged_fx, fSNRPenaltyMerged_exp, L_negate( fSNRPenalty1_fx ), fSNRPenalty1_exp, &temp_exp ); + fMergedCost_fx = BASOP_Util_Add_Mant32Exp( temp, temp_exp, L_negate( fSNRPenalty2_fx ), fSNRPenalty2_exp, fMergedCost_exp ); + fMergedCost_fx = BASOP_Util_Add_Mant32Exp( fMergedCost_fx, *fMergedCost_exp, RMSEnvBits_fx, 21, fMergedCost_exp ); + // fMergedCost = fSNRPenaltyMerged - fSNRPenalty1 - fSNRPenalty2 + (float) iRMSEnvBitsMerged - (float) iRMSEnvBits1 - (float) iRMSEnvBits2; + return fMergedCost_fx; +} + +/*-------------------------------------------------------------------* + * Function ComputeGreedyGroups3() + * + * + *-------------------------------------------------------------------*/ +static void ComputeGreedyGroups3( + RMSEnvelopeGrouping *psRMSEnvelopeGrouping, + const int32_t iChannels, + const int32_t iNumBands, + const int32_t *piBandwidths, + const int32_t iMaxGroups ) +{ + + Word32 iDone = 0; + Word32 iNumGroups = psRMSEnvelopeGrouping->iMaxGroups; + WHILE( EQ_32( iDone, 0 ) ) + { + GMNode *psGMNode; + GMNode *psBestGMNode; + /* Instead of 1e20f*/ + Word32 fBestMergeCost_fx = 1455191552; // mantissa of 1e20f + move32(); + Word16 fBestMergeCost_exp = 67; // exp of 1e20f + move16(); + Word16 Flag = 0; + move16(); + psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0]; + psBestGMNode = NULL; + WHILE( psGMNode->psNext != NULL ) + { + Word32 fMergeCost_fx = 0; + move32(); + Word16 fMergeCost_exp = 0; + move16(); + fMergeCost_fx = TryMerge2( iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, psRMSEnvelopeGrouping->ppfBandEnergydB_fx, psGMNode, psGMNode->psNext, &fMergeCost_exp ); + IF( LT_32( fMergeCost_fx, 0 ) && ( GT_32( fBestMergeCost_fx, 0 ) ) ) + { + + Flag = 1; + move16(); + } + ELSE IF( ( GT_32( fMergeCost_fx, 0 ) && ( LT_32( fBestMergeCost_fx, 0 ) ) ) ) + { + Flag = -1; + move16(); + } + ELSE + { + Flag = BASOP_Util_Cmp_Mant32Exp( fBestMergeCost_fx, fBestMergeCost_exp, fMergeCost_fx, fMergeCost_exp ); + } + IF( EQ_32( Flag, 1 ) ) + { + fBestMergeCost_fx = fMergeCost_fx; + move32(); + fBestMergeCost_exp = fMergeCost_exp; + move16(); + psBestGMNode = psGMNode; + } + + psGMNode = psGMNode->psNext; + } + + IF( ( GT_32( fBestMergeCost_fx, 0 ) && ( LE_32( iNumGroups, iMaxGroups ) ) ) ) + { + iDone++; + } + ELSE IF( ( psBestGMNode != NULL ) && ( psBestGMNode->psNext != NULL ) ) + { + psBestGMNode->iGroupLength = L_add( psBestGMNode->psNext->iGroupLength, psBestGMNode->iGroupLength ); + psBestGMNode->fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 ); + psBestGMNode->fGroupSNRPenalty_exp = 1; + move16(); + psBestGMNode->psNext = psBestGMNode->psNext->psNext; + iNumGroups--; + } + ELSE + { + iDone++; // This only catches a problem + } + } + return; +} +/*-------------------------------------------------------------------* + * Function ComputeRMSEnvelope() + * + * + *-------------------------------------------------------------------*/ +static void ComputeRMSEnvelope( + const Word32 iChannels, + const Word32 iNumBands, + const Word32 iNumGroups, + const Word32 *piGroupLengths, + Word32 **ppfBandEnergy_man, + Word16 **ppfBandEnergy_exp, + Word32 ***pppiRMSEnvelope ) +{ + Word32 n; + Word32 fGroupEnergy_fx; + Word16 fGroupEnergy_exp; + Word32 temp; + // FILE *fp = fopen( "RmsEnvelope_fixed", "ab+" ); + // FILE *fp1 = fopen( "RmsEnvelope_float", "ab+" ); + FOR( n = 0; n < iChannels; n++ ) + { + Word32 b; + Word32 iChanOffset; + + iChanOffset = L_mult0( extract_l( n ), extract_l( iNumBands ) ); + + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 k; + Word32 iBlockOffset; + iBlockOffset = 0; + FOR( k = 0; k < iNumGroups; k++ ) + { + Word32 m; + fGroupEnergy_exp = 0; + move16(); + fGroupEnergy_fx = 0; + move32(); + FOR( m = 0; m < piGroupLengths[k]; m++ ) + { + fGroupEnergy_fx = BASOP_Util_Add_Mant32Exp( ppfBandEnergy_man[iBlockOffset][b + iChanOffset], ppfBandEnergy_exp[iBlockOffset][b + iChanOffset], fGroupEnergy_fx, fGroupEnergy_exp, &fGroupEnergy_exp ); + iBlockOffset++; + } + fGroupEnergy_fx = Mpy_32_32( fGroupEnergy_fx, Inv_grp_length[piGroupLengths[k]] ); // Division by iGroupLength + fGroupEnergy_fx = BASOP_Util_Log2( fGroupEnergy_fx ); + move32(); + fGroupEnergy_fx = L_add( fGroupEnergy_fx, L_shl( L_deposit_l( fGroupEnergy_exp ), WORD32_BITS - 1 - LD_DATA_SCALE ) ); /*Q25*/ + temp = ( fGroupEnergy_fx > 0 ) ? L_add( fGroupEnergy_fx, ONE_IN_Q24 ) : L_negate( L_add( L_negate( fGroupEnergy_fx ), ONE_IN_Q24 ) ); // Q25 + temp = L_shr( temp, 25 ); + temp = ( temp > ENV_MIN ) ? temp : ENV_MIN; + temp = ( temp < ENV_MAX ) ? temp : ENV_MAX; + pppiRMSEnvelope[n][k][b] = temp; + // fprintf( fp,"%d\n", pppiRMSEnvelope[n][k][b] ); + } + } + } + // fclose( fp ); + /* fclose( fp1 );*/ + return; +} + +/*-------------------------------------------------------------------* + * Function LimitRMSEnvelope() + * + * + *-------------------------------------------------------------------*/ +static void LimitRMSEnvelope( + const Word32 iBandCount, + const Word32 iRMSDeltaMax, + const Word32 iRMSDeltaMin, + Word32 *piRMSEnvelope ) +{ + Word32 iBand; + Word32 iLastSCF; + + /* Increase low envelope values to ensure that the scale factors traces the large values correctly (checking for max deltas) */ + iLastSCF = piRMSEnvelope[iBandCount - 1]; + move32(); + for ( iBand = iBandCount - 2; iBand > -1; iBand-- ) + { + Word32 iDelta; + + iDelta = L_sub( iLastSCF, piRMSEnvelope[iBand] ); + + IF( GT_32( iDelta, iRMSDeltaMax ) ) + { +#ifdef DEBUG_VERBOSE + printf( "WARNING RMS envelope delta limited\n" ); +#endif + piRMSEnvelope[iBand] = L_add( L_sub( iDelta, iRMSDeltaMax ), piRMSEnvelope[iBand] ); + } + + iLastSCF = piRMSEnvelope[iBand]; + move32(); + } + + /* Increase low envelope values to ensure that the envelope traces the large values correctly (checking for min deltas)*/ + iLastSCF = piRMSEnvelope[0]; + FOR( iBand = 1; iBand < iBandCount; iBand++ ) + { + Word32 iDelta; + + iDelta = L_sub( piRMSEnvelope[iBand], iLastSCF ); + + IF( LT_32( iDelta, iRMSDeltaMin ) ) + { +#ifdef DEBUG_VERBOSE + printf( "WARNING RMS envelope delta limited\n" ); +#endif + piRMSEnvelope[iBand] = L_add( piRMSEnvelope[iBand], L_sub( iRMSDeltaMin, iDelta ) ); + } + + iLastSCF = piRMSEnvelope[iBand]; + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * Function ComputeEnvelopeGrouping() + * + * + *-------------------------------------------------------------------*/ +void ComputeEnvelopeGrouping( + RMSEnvelopeGrouping *psRMSEnvelopeGrouping, + const Word32 iChannels, + const Word32 iNumBands, + const Word32 *piBandwidths, + Word32 ***pppfReal_fx, + Word32 ***pppfImag_fx, + Word32 *piNumGroups, + Word32 *piGroupLengths, + Word32 ***pppiRMSEnvelope, + Word16 q_final ) +{ + Word32 n; + GMNode *psGMNode; + + /* Compute Band Energies */ + ComputeBandEnergy( iChannels, psRMSEnvelopeGrouping->iNumBlocks, iNumBands, piBandwidths, pppfReal_fx, pppfImag_fx, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, psRMSEnvelopeGrouping->ppfBandEnergydB_fx, psRMSEnvelopeGrouping->ppfWeight_man, psRMSEnvelopeGrouping->ppfWeight_exp, q_final ); + /* Init GMNodes */ + psRMSEnvelopeGrouping->psGMNodes[0].iGroupStart = 0; + move32(); + psRMSEnvelopeGrouping->psGMNodes[0].iGroupLength = 2; + move32(); + psRMSEnvelopeGrouping->psGMNodes[0].psNext = NULL; + psRMSEnvelopeGrouping->psGMNodes[0].iGroupRMSEnvelopeCost = -1; + move32(); + psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 ); + psRMSEnvelopeGrouping->psGMNodes[0].fGroupSNRPenalty_exp = 1; + move16(); + FOR( n = 1; n < psRMSEnvelopeGrouping->iMaxGroups; n++ ) + { + psRMSEnvelopeGrouping->psGMNodes[n - 1].psNext = &psRMSEnvelopeGrouping->psGMNodes[n]; + psRMSEnvelopeGrouping->psGMNodes[n].iGroupStart = L_shl( n, 1 ); + move32(); + psRMSEnvelopeGrouping->psGMNodes[n].iGroupLength = 2; + move32(); + psRMSEnvelopeGrouping->psGMNodes[n].iGroupRMSEnvelopeCost = -1; + move32(); + psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_fx = L_negate( ONE_IN_Q30 ); + psRMSEnvelopeGrouping->psGMNodes[n].fGroupSNRPenalty_exp = 1; + move16(); + psRMSEnvelopeGrouping->psGMNodes[n].psNext = NULL; + } + /* Perform grouping via Greedy Merge */ + /* Allows control over max groups can call using 16 if want same as previous call */ + ComputeGreedyGroups3( psRMSEnvelopeGrouping, iChannels, iNumBands, piBandwidths, psRMSEnvelopeGrouping->iNumBlocks ); + /* Calc Groups from Merge Results */ + *piNumGroups = 0; + move32(); + psGMNode = &psRMSEnvelopeGrouping->psGMNodes[0]; + WHILE( psGMNode != NULL ) + { + piGroupLengths[*piNumGroups] = psGMNode->iGroupLength; + move32(); + *piNumGroups = L_add( *piNumGroups, 1 ); + psGMNode = psGMNode->psNext; + } + /* Compute RMS Envelope given group lengths */ + ComputeRMSEnvelope( iChannels, iNumBands, *piNumGroups, piGroupLengths, psRMSEnvelopeGrouping->ppfBandEnergy_man, psRMSEnvelopeGrouping->ppfBandEnergy_exp, pppiRMSEnvelope ); + + /* Envelope Tenting */ + FOR( n = 0; n < iChannels; n++ ) + { + Word32 k; + FOR( k = 0; k < *piNumGroups; k++ ) + { + LimitRMSEnvelope( iNumBands, ENV_DELTA_MAX, ENV_DELTA_MIN, pppiRMSEnvelope[n][k] ); + } + } + + return; +} +#endif diff --git a/lib_isar/isar_cnst.h b/lib_isar/isar_cnst.h new file mode 100644 index 000000000..72ff5b892 --- /dev/null +++ b/lib_isar/isar_cnst.h @@ -0,0 +1,159 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_CNST_H +#define ISAR_CNST_H + +#include +#include "options.h" + +/* clang-format off */ + +#ifdef SPLIT_REND_WITH_HEAD_ROT + +/*----------------------------------------------------------------------------------* + * Split Binaural Rendering Constants + *----------------------------------------------------------------------------------*/ + +typedef enum +{ + PCM_INT16, + PCM_FLOAT32, + PCM_NOT_KNOW = 0xffff +} PCM_RESOLUTION; + +typedef enum +{ + ANY_YAW, + PITCH_ONLY, + ANY_ROLL, + PRED_ONLY, + PRED_ROLL_ONLY, + COM_GAIN_ONLY, + LR_GAIN_ONLY +} ISAR_SPLIT_REND_POSE_TYPE; + + +#define CLDFB_PLC_XF 2 /* Length of cross-fade into first good frame after frame loss in CLDFB cols. */ + +#define SPLIT_REND_MAX_YAW_ONLY_POSES 2 +#define SPLIT_REND_MAX_PITCH_ONLY_POSES 2 +#define SPLIT_REND_MAX_ROLL_ONLY_POSES 2 +#define SPLIT_REND_MAX_ONE_AXIS_MD_POSES 2 +#define MAX_EXTRAPOLATION_ANGLE 15.0f /* this means additional 15 degrees can be extrapolated on top of MD probing poses*/ +#define MAX_EXTRAPOLATION_ANGLE_Q22 (62914560) /* this means additional 15 degrees can be extrapolated on top of MD probing poses*/ + +#define MAX_HEAD_ROT_POSES ( 2 + SPLIT_REND_MAX_YAW_ONLY_POSES + SPLIT_REND_MAX_PITCH_ONLY_POSES + SPLIT_REND_MAX_ROLL_ONLY_POSES ) +#define MAX_SPLIT_REND_MD_BANDS 20 +#define MAX_SPLIT_MD_SUBFRAMES 1 +#define COMPLEX_MD_BAND_THRESH MAX_SPLIT_REND_MD_BANDS +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS +#define COMPLEX_MD_BAND_THRESH_LOW 4 +#define COMPLEX_MD_BAND_THRESH_HIGH 10 +#else +#define COMPLEX_MD_BAND_THRESH_LOW 5 +#endif +#define SPLIT_REND_RO_MD_BAND_THRESH 4 + +#define ISAR_SPLIT_REND_PRED_63QUANT_PNTS_LOG2_CEIL 6 +#define ISAR_SPLIT_REND_PRED_31QUANT_PNTS_LOG2_CEIL 5 +#define ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS_LOG2_CEIL 5 +#define ISAR_SPLIT_REND_D_QUANT_PNTS_LOG2_CEIL 4 + +#define ISAR_SPLIT_REND_PRED_MIN_VAL_Q30 -1503238553 //Q30 +#define ISAR_SPLIT_REND_PRED_MAX_VAL_Q30 1503238553 //Q30 + +#define ISAR_SPLIT_REND_NUM_QUANT_STRATS 4 +#define ISAR_SPLIT_REND_PRED_63QUANT_PNTS 63 +#define ISAR_SPLIT_REND_PRED_31QUANT_PNTS 31 +#define ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS 31 +#define ISAR_SPLIT_REND_D_QUANT_PNTS 15 +#define ISAR_SPLIT_REND_PRED_MIN_VAL -1.4f +#define ISAR_SPLIT_REND_PRED_MAX_VAL 1.4f + +#define ISAR_SPLIT_REND_PITCH_G_MIN_VAL 0.5f +#define ISAR_SPLIT_REND_PITCH_G_MAX_VAL 1.5f +#define ISAR_SPLIT_REND_PITCH_G_MIN_VAL_Q30 (1<<29) //0.5f in Q30 +#define ISAR_SPLIT_REND_PITCH_G_MAX_VAL_Q30 1610612736 //1.5f in Q30 +#define ISAR_SPLIT_REND_PITCH_G_QUANT_PNTS ISAR_SPLIT_REND_D_QUANT_PNTS +#define ISAR_SPLIT_REND_D_MIN_VAL 0.0f +#define ISAR_SPLIT_REND_D_MAX_VAL 1.0f +#define ISAR_SPLIT_REND_D_MIN_VAL_FX 0 //Q31 +#define ISAR_SPLIT_REND_D_MAX_VAL_FX MAX_32 //Q31 + +#define ISAR_SPLIT_REND_PRED_ROLL_Q_STEP ( ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) / ( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS - 1 ) ) +#define ISAR_SPLIT_REND_PRED_ROLL_Q_STEP_Q31 200431807 +#define ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP_Q26 719023543 +#define ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP ( ( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) ) +#define ISAR_SPLIT_REND_PRED31_Q_STEP ( ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) / ( ISAR_SPLIT_REND_PRED_31QUANT_PNTS - 1 ) ) +#define ISAR_SPLIT_REND_PRED31_1BYQ_STEP ( ( ISAR_SPLIT_REND_PRED_31QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) ) +#define ISAR_SPLIT_REND_PRED63_Q_STEP ( ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) / ( ISAR_SPLIT_REND_PRED_63QUANT_PNTS - 1 ) ) +#define ISAR_SPLIT_REND_PRED63_1BYQ_STEP ( ( ISAR_SPLIT_REND_PRED_63QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PRED_MAX_VAL - ISAR_SPLIT_REND_PRED_MIN_VAL ) ) + +#define ISAR_SPLIT_REND_PRED31_Q_STEP_FX_Q31 200431807 +#define ISAR_SPLIT_REND_PRED31_1BYQ_STEP_FX_Q26 719023543 +#define ISAR_SPLIT_REND_PRED63_Q_STEP_FX_Q31 96983132 +#define ISAR_SPLIT_REND_PRED63_1BYQ_STEP_FX_Q26 1485981989 + +#define ISAR_SPLIT_REND_D_Q_STEP ( ( ISAR_SPLIT_REND_D_MAX_VAL - ISAR_SPLIT_REND_D_MIN_VAL ) / ( ISAR_SPLIT_REND_D_QUANT_PNTS - 1 ) ) +#define ISAR_SPLIT_REND_D_1BYQ_STEP ( ( ISAR_SPLIT_REND_D_QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_D_MAX_VAL - ISAR_SPLIT_REND_D_MIN_VAL ) ) +#define ISAR_SPLIT_REND_PITCH_G_Q_STEP ( ( ISAR_SPLIT_REND_PITCH_G_MAX_VAL - ISAR_SPLIT_REND_PITCH_G_MIN_VAL ) / ( ISAR_SPLIT_REND_PITCH_G_QUANT_PNTS - 1 ) ) +#define ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP ( ( ISAR_SPLIT_REND_PITCH_G_QUANT_PNTS - 1 ) / ( ISAR_SPLIT_REND_PITCH_G_MAX_VAL - ISAR_SPLIT_REND_PITCH_G_MIN_VAL ) ) +#define ISAR_SPLIT_REND_D_Q_STEP_Q31 153391689 +#define ISAR_SPLIT_REND_D_1BYQ_STEP_Q27 (14 << 27) //Q27 +#define ISAR_SPLIT_REND_PITCH_G_Q_STEP_Q31 153391689 +#define ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP_Q27 (14 << 27) //Q27 + + +#define ISAR_SPLIT_REND_HEAD_POSE_BITS 9 +#define ISAR_SPLIT_REND_DOF_BITS 2 +#define ISAR_SPLIT_REND_HQ_MODE_BITS 1 +#define ISAR_SPLIT_REND_ROT_AXIS_BITS 3 +#define ISAR_SPLIT_REND_RO_FLAG_BITS 1 + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#define IVAS_LC3PLUS_MAX_NUM_DECODERS 2 +#endif +/*----------------------------------------------------------------------------------* + * Split rendering bitrate constants + *----------------------------------------------------------------------------------*/ + +#define SPLIT_REND_256k 256000 +#define SPLIT_REND_320k 320000 +#define SPLIT_REND_384k 384000 +#define SPLIT_REND_512k 512000 +#define SPLIT_REND_768k 768000 + +#endif /*SPLIT_REND_WITH_HEAD_ROT */ + +#endif /*ISAR_CNST_H */ +/* clang-format on */ diff --git a/lib_isar/isar_lc3plus_common.c b/lib_isar/isar_lc3plus_common.c new file mode 100644 index 000000000..32e30e97c --- /dev/null +++ b/lib_isar/isar_lc3plus_common.c @@ -0,0 +1,89 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include "options.h" +#include "isar_lc3plus_common.h" +#include "ivas_error.h" +#include "lc3.h" + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-----------------------------------------------------------------------------------------* + * Function ISAR_LC3PLUS_LC3plusErrToIvasErr() + * + * + *-----------------------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr( + const LC3PLUS_Error lc3PlusError ) +{ + switch ( lc3PlusError ) + { + case LC3PLUS_OK: + return IVAS_ERR_OK; + case LC3PLUS_BITRATE_ERROR: + return IVAS_ERR_LC3PLUS_INVALID_BITRATE; + default: + break; + } + + return IVAS_ERR_INTERNAL; +} +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError ) +{ + switch ( lc3PlusRtpError ) + { + case LC3PLUS_RTP_ERR_NO_ERROR: + return IVAS_ERR_OK; + case LC3PLUS_RTP_ERR_NULL_PTR: + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + case LC3PLUS_RTP_ERR_INVALID_PARAMETERS: + return IVAS_ERR_WRONG_PARAMS; + case LC3PLUS_RTP_ERR_NOT_IMPLEMENTED: + return IVAS_ERR_NOT_IMPLEMENTED; + case LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION: + return IVAS_ERR_INTERNAL; + case LC3PLUS_RTP_ERR_INVALID_BITSTREAM: + return IVAS_ERR_UNEXPECTED_LC3PLUS_BITSTREAM; + case LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE: + return IVAS_ERR_INVALID_BUFFER_SIZE; + case LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED: + return IVAS_ERR_INTERNAL; + case LC3PLUS_RTP_ERR_GENERIC_ERROR: + default: + break; + } + + return IVAS_ERR_UNKNOWN; +} +#endif +#endif diff --git a/lib_isar/isar_lc3plus_common.h b/lib_isar/isar_lc3plus_common.h new file mode 100644 index 000000000..08ffff60a --- /dev/null +++ b/lib_isar/isar_lc3plus_common.h @@ -0,0 +1,72 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_LC3PLUS_COM_H +#define ISAR_LC3PLUS_COM_H + + +#include +#include "options.h" +#include "ivas_error.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "lc3.h" +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#include "isar_lc3plus_payload.h" +#endif + +/*! common configuration parameters between encoder and decoder */ +typedef struct LC3PLUS_CONFIG +{ + /*! frame duration in microseconds [10000, 5000, 2500] */ + int16_t lc3plus_frame_duration_us; + /*! isar frame duration in microseconds [20000, 10000, 5000] */ + int16_t isar_frame_duration_us; + /*! sampling rate*/ + int32_t samplerate; + /*! number of channels */ + int16_t channels; +#if defined ISAR_BITSTREAM_UPDATE_LC3PLUS || defined ISAR_BITSTREAM_UPDATE_LC3PLUS + /*! high resolution mode enabled (1) or disabled (0)*/ + int16_t high_res_mode_enabled; +#endif +} LC3PLUS_CONFIG; + +/*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */ +ivas_error ISAR_LC3PLUS_LC3plusErrToIvasErr( const LC3PLUS_Error lc3PlusError ); + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +/*! utility function to convert LC3PLUS_Errors to the suitable ivas_error */ +ivas_error IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( const LC3PLUS_RTP_ERR lc3PlusRtpError ); +#endif + +#endif /* SPLIT_REND_WITH_HEAD_ROT */ +#endif /* ISAR_LC3PLUS_COM_H */ diff --git a/lib_isar/isar_lc3plus_dec.c b/lib_isar/isar_lc3plus_dec.c new file mode 100644 index 000000000..1c63158b3 --- /dev/null +++ b/lib_isar/isar_lc3plus_dec.c @@ -0,0 +1,857 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "prot.h" +#include "ivas_prot.h" +#include "isar_lc3plus_dec.h" +#include "isar_lc3plus_common.h" +#include "lc3.h" +#include "ivas_error_utils.h" +#include "wmc_auto.h" + +#ifdef SPLIT_REND_WITH_HEAD_ROT + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +/*------------------------------------------------------------------------- + * isar_LC3PLUS_AllocateSubframeDecodingMatrix() + * + * + *------------------------------------------------------------------------*/ + +static void isar_LC3PLUS_DEC_FreeSubframeDecodingMatrix( + int16_t **subframeChannelMatrix ) +{ + for ( int16_t i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + free( subframeChannelMatrix[i] ); + } + + free( subframeChannelMatrix ); + + return; +} +#endif + + +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_Open() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_DEC_Open( + const LC3PLUS_CONFIG config, /* i : LC3plus decoder configuration */ + ISAR_LC3PLUS_DEC_HANDLE *handle /* o : decoder handle */ +) +{ + LC3PLUS_Error err; + int32_t decoder_size; + Word32 scratch_size; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t i; + + if ( 0 == config.lc3plus_frame_duration_us ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" ); + } +#else + int16_t lc3plusFrameIdx; + int16_t numLC3plusFramesPerIvasFrame; + int16_t i; +#endif + + if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_DEC_HANDLE ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( config.channels > IVAS_LC3PLUS_MAX_NUM_DECODERS ) + { + return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "Maximum number of channels exceeds IVAS_LC3PLUS_MAX_NUM_DECODERS\n" ); + } +#else + + if ( 0 == config.lc3plus_frame_duration_us ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid lc3plus_frame_duration_us (0)\n" ); + } + numLC3plusFramesPerIvasFrame = (int16_t) ( config.isar_frame_duration_us / config.lc3plus_frame_duration_us ); +#endif + + + ( *handle )->num_decs = 0; + ( *handle )->pcm_conversion_buffer = NULL; + ( *handle )->handles = NULL; + ( *handle )->selective_decoding_states = NULL; + ( *handle )->bitstream_caches = NULL; + + if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_HANDLE ) ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); + } + + if ( ( ( *handle )->selective_decoding_states = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE * ) ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); + } + + for ( i = 0; i < config.channels; ++i ) + { + ( *handle )->handles[i] = NULL; + ( *handle )->selective_decoding_states[i] = NULL; + } + + if ( ( ( *handle )->bitstream_caches = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_BITSTREAM_CACHE * ) ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); + } + for ( i = 0; i < config.channels; ++i ) + { + ( *handle )->bitstream_caches[i] = NULL; + } + + ( *handle )->num_decs = config.channels; + for ( int32_t iCh = 0; iCh < config.channels; iCh++ ) + { + ( *handle )->selective_decoding_states[iCh] = NULL; + if ( NULL != ( *handle )->bitstream_caches ) + { + ( *handle )->bitstream_caches[iCh] = NULL; + } + /* allocate and configure LC3plus decoder */ + decoder_size = lc3plus_dec_get_size( config.samplerate, 1, LC3PLUS_PLC_ADVANCED ); + if ( 0 == decoder_size ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_dec_get_size failed\n" ); + } + + if ( ( ( *handle )->handles[iCh] = malloc( decoder_size ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, config.high_res_mode_enabled ); +#else + err = lc3plus_dec_init( ( *handle )->handles[iCh], config.samplerate, 1, LC3PLUS_PLC_ADVANCED, 0 ); +#endif + if ( LC3PLUS_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_init failed\n" ); + } + + err = lc3plus_dec_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 ); + if ( LC3PLUS_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec_set_frame_dms failed\n" ); + } + + /* allocate and configure per LC3plus decoder skip state */ + if ( ( ( *handle )->selective_decoding_states[iCh] = malloc( sizeof( ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE ) ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); + } + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( ( ( *handle )->selective_decoding_states[iCh]->frame_actions = malloc( numLC3plusFramesPerIvasFrame * sizeof( SelectiveDecAction ) ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); + } +#endif + + ( *handle )->selective_decoding_states[iCh]->has_skipped_a_frame = 0; + ( *handle )->selective_decoding_states[iCh]->shall_decode_cached_frame = 0; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *handle )->selective_decoding_states[iCh]->frame_action = DEC_ACTION_DECODE_AND_USE; +#else + for ( lc3plusFrameIdx = 0; lc3plusFrameIdx < numLC3plusFramesPerIvasFrame; lc3plusFrameIdx++ ) + { + ( *handle )->selective_decoding_states[iCh]->frame_actions[lc3plusFrameIdx] = DEC_ACTION_DECODE_AND_USE; + } +#endif + + /* allocate and configure per LC3plus decoder bitstream cache */ + if ( ( ( *handle )->bitstream_caches[iCh] = malloc( sizeof( ISAR_LC3PLUS_DEC_BITSTREAM_CACHE ) ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/; +#else + ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity = 400 /*LC3plus max non-HR octet count*/ * numLC3plusFramesPerIvasFrame; +#endif + if ( ( ( *handle )->bitstream_caches[iCh]->bitstream_cache = malloc( ( *handle )->bitstream_caches[iCh]->bitstream_cache_capacity ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder\n" ); + } + ( *handle )->bitstream_caches[iCh]->bitstream_cache_size = 0; + } + + ( *handle )->config = config; + if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" ); + } + + if ( ( ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder wrapper pcm_conversion_buffer\n" ); + } + + scratch_size = lc3plus_dec_get_scratch_size( ( *handle )->handles[0] ); + if ( ( ( *handle )->scratch = malloc( sizeof( uint8_t ) * scratch_size ) ) == NULL ) + { + ISAR_LC3PLUS_DEC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus decoder wrapper scratch\n" ); + } + + return IVAS_ERR_OK; +} + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( + int16_t ***subframeChannelMatrix, + const uint32_t num_decs ) +{ + int16_t i; + + if ( ( *subframeChannelMatrix = malloc( MAX_PARAM_SPATIAL_SUBFRAMES * sizeof( int16_t * ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "subframeChannelMatrix allocation failed\n" ); + } + + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + ( *subframeChannelMatrix )[i] = NULL; + } + + for ( i = 0; i < MAX_PARAM_SPATIAL_SUBFRAMES; i++ ) + { + if ( ( ( *subframeChannelMatrix )[i] = malloc( num_decs * sizeof( int16_t ) ) ) == NULL ) + { + isar_LC3PLUS_DEC_FreeSubframeDecodingMatrix( *subframeChannelMatrix ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "subframeChannelMatrix allocation failed\n" ); + } + } + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */ + int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] ) +{ + int16_t numIvasSubFramesPerLC3frame; + uint32_t decIdx; + int16_t ivasSubframeIdx; + int16_t effectiveIsarSubframeDuration; + int16_t actual_num_spatial_subframes; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "ISAR_LC3PLUS_DEC_HANDLE is NULL\n" ); + } + + if ( NULL == subframeChannelMatrix ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "subframeChannelMatrix is NULL\n" ); + } + + if ( handle->config.lc3plus_frame_duration_us == 0 || handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "invalid isar_frame_duration_us/lc3plus_frame_duration_us values\n" ); + } + + effectiveIsarSubframeDuration = (int16_t) ( handle->config.isar_frame_duration_us == 20000 ? handle->config.isar_frame_duration_us / MAX_PARAM_SPATIAL_SUBFRAMES : handle->config.isar_frame_duration_us ); + numIvasSubFramesPerLC3frame = (int16_t) handle->config.lc3plus_frame_duration_us / effectiveIsarSubframeDuration; + actual_num_spatial_subframes = (int16_t) handle->config.isar_frame_duration_us / effectiveIsarSubframeDuration; + /* 0.5(0) = 10ms lc3plus, 5ms subframe */ + if ( numIvasSubFramesPerLC3frame != 1 ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Selective decoding is only implemented for aligned IVAS-Subframes & LC3plus \n" ); + } + + /* map subframeChannelMatrix to lc3plus skip states */ + /* 1st pass: Flag the required frames */ + for ( decIdx = 0; decIdx < handle->num_decs; decIdx++ ) + { + for ( ivasSubframeIdx = 0; ivasSubframeIdx < actual_num_spatial_subframes; ivasSubframeIdx++ ) + { + if ( 1 == subframeChannelMatrix[ivasSubframeIdx][decIdx] ) + { + /* subframe needed by the user, definitely decode */ + handle->selective_decoding_states[decIdx]->frame_actions[ivasSubframeIdx] = DEC_ACTION_DECODE_AND_USE; + } + else + { + + /* subframe not needed by the user, but might be required to re-initialize a decoder after inactivity */ + if ( + ( ivasSubframeIdx != actual_num_spatial_subframes - 1 ) && 1 == subframeChannelMatrix[ivasSubframeIdx + 1][decIdx] ) + { + /* ... but if the following subframe is required, it needs to be decoded and dropped */ + handle->selective_decoding_states[decIdx]->frame_actions[ivasSubframeIdx] = DEC_ACTION_DECODE_AND_DROP; + } + else + { + handle->selective_decoding_states[decIdx]->frame_actions[ivasSubframeIdx] = DEC_ACTION_SKIP; + } + } + } + } + + /* if a decoder was paused before, it needs to either: + * - Decode the cached frame (if available) and the first required frame OR + * - Decode the previous LC3plus subframe, even if it isn't needed by the user */ + for ( decIdx = 0; decIdx < handle->num_decs; decIdx++ ) + { + if ( handle->selective_decoding_states[decIdx]->has_skipped_a_frame ) + { + /* find the first frame required by the user */ + for ( ivasSubframeIdx = 0; ivasSubframeIdx < actual_num_spatial_subframes; ivasSubframeIdx++ ) + { + if ( DEC_ACTION_DECODE_AND_USE == handle->selective_decoding_states[decIdx]->frame_actions[ivasSubframeIdx] ) + { + /* The first required frame is the first subframe. To flush the decoder, the cached frame must be decoded and dropped */ + if ( 0 == ivasSubframeIdx ) + { + handle->selective_decoding_states[decIdx]->shall_decode_cached_frame = 1; + break; + } + /* The first required frame is not the first frame, so the cache is useless. Instead we decode & drop the previous frame*/ + else + { + handle->selective_decoding_states[decIdx]->frame_actions[ivasSubframeIdx - 1] = DEC_ACTION_DECODE_AND_DROP; + break; + } + } + } + } + } + + /* if a dec gets paused & caching is activated we need to flag the last useful LC3plus frame for caching */ + for ( decIdx = 0; decIdx < handle->num_decs; decIdx++ ) + { + for ( ivasSubframeIdx = 0; ivasSubframeIdx < actual_num_spatial_subframes; ivasSubframeIdx++ ) + { + if ( handle->selective_decoding_states[decIdx]->frame_actions[ivasSubframeIdx] == DEC_ACTION_SKIP && handle->selective_decoding_states[decIdx]->frame_actions[actual_num_spatial_subframes - 1] != DEC_ACTION_DECODE_AND_USE ) + { + handle->selective_decoding_states[decIdx]->frame_actions[actual_num_spatial_subframes - 1] = DEC_ACTION_CACHE; + } + } + } + + return IVAS_ERR_OK; +} +#endif + + +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_GetDelay() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_DEC_GetDelay( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */ + int32_t *delayInSamples /* o : decoder delay in number of samples per channel */ +) +{ + int32_t tmpDelayInSamples; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "ISAR_LC3PLUS_DEC_HANDLE is NULL\n" ); + } + if ( NULL == delayInSamples ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "delayInSamples is NULL\n" ); + } + + *delayInSamples = 0; + /* sanity check whether all encoders are actually configured identically */ + for ( uint32_t iDec = 0; iDec < handle->num_decs; iDec++ ) + { + if ( NULL == handle->handles[iDec] ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus decoder handle is NULL\n" ); + } + + tmpDelayInSamples = lc3plus_dec_get_delay( handle->handles[iDec] ); + if ( 0 != *delayInSamples && tmpDelayInSamples != *delayInSamples ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Not all mono LC3plus decoders are configured identically\n" ); + } + + *delayInSamples = tmpDelayInSamples; + } + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_Close() + * + * + *------------------------------------------------------------------------*/ + +void ISAR_LC3PLUS_DEC_Close( + ISAR_LC3PLUS_DEC_HANDLE *handle /* i/o: Pointer to LC3plus decoder handle */ +) +{ + if ( NULL == handle || NULL == *handle ) + { + return; + } + for ( uint32_t iDec = 0; iDec < ( *handle )->num_decs; iDec++ ) + { + if ( NULL != ( *handle )->handles && NULL != ( *handle )->handles[iDec] ) + { + free( ( *handle )->handles[iDec] ); + } + + if ( NULL != ( *handle )->selective_decoding_states && NULL != ( *handle )->selective_decoding_states[iDec] ) + { +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + free( ( *handle )->selective_decoding_states[iDec]->frame_actions ); +#endif + free( ( *handle )->selective_decoding_states[iDec] ); + } + + if ( NULL != ( *handle )->bitstream_caches && NULL != ( *handle )->bitstream_caches[iDec] ) + { + free( ( *handle )->bitstream_caches[iDec]->bitstream_cache ); + free( ( *handle )->bitstream_caches[iDec] ); + } + } + + if ( NULL != ( *handle )->pcm_conversion_buffer ) + { + free( ( *handle )->pcm_conversion_buffer ); + } + if ( NULL != ( *handle )->scratch ) + { + free( ( *handle )->scratch ); + } + + free( ( *handle )->handles ); + + if ( NULL != ( *handle )->bitstream_caches ) + { + free( ( *handle )->bitstream_caches ); + } + free( ( *handle )->selective_decoding_states ); + + free( *handle ); + *handle = NULL; + + return; +} + + +/*------------------------------------------------------------------------- + * decode_or_conceal_one_lc3plus_frame() + * + * + *------------------------------------------------------------------------*/ + +static ivas_error decode_or_conceal_one_lc3plus_frame( + LC3PLUS_Dec *dec, + uint8_t *bitstream_in, + const int32_t bitstream_in_length, + int16_t **pcm_out_buffer, + const int32_t badFrameIndicator, + uint8_t *scratch ) +{ + LC3PLUS_Error err; + + push_wmops( "lc3plus_dec16" ); + err = lc3plus_dec16( dec, bitstream_in, bitstream_in_length, pcm_out_buffer, scratch, badFrameIndicator ); + pop_wmops(); + + if ( err == LC3PLUS_DECODE_ERROR && 1 == badFrameIndicator ) + { + /* LC3PLUS_DECODE_ERROR && badFrameIndicator means that the decoder has successfully concealed, which is actually OK. */ + err = LC3PLUS_OK; + } + + if ( err != LC3PLUS_OK ) + { + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_dec16 failed\n" ); + } + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * isar_LC3PLUS_DEC_Decode_or_Conceal_internal() + * + * + *------------------------------------------------------------------------*/ + +static ivas_error isar_LC3PLUS_DEC_Decode_or_Conceal_internal( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder configuration */ + uint8_t *bitstream_in, /* i : pointer to input bitstream */ + int32_t bitstream_in_size, /* i : size of bitstream_in */ + const int16_t badFrameIndicator, /* i : bad frame indicator. If set to 1, triggers concealment */ + Word32 **pcm_out /* o : decoded samples */ +) +{ + uint32_t iDec; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t config_num_media_times; + int32_t iMediaTime; + int32_t iFtd; + LC3PLUS_RTP_PAYLOAD payload; +#else + int32_t iLc3plusFrame; + int32_t lc3framesPerIvasFrame; + int32_t bitstreamOffsetPerCoder; + uint8_t *bitstream_in_iter = bitstream_in; +#endif + int32_t ivasSampleIndex; + int16_t numSamplesPerLC3plusChannel; + ivas_error err; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Dec_Wrap_Handle is NULL\n" ); + } + if ( NULL == bitstream_in ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_in is NULL\n" ); + } + if ( NULL == pcm_out ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_out is NULL\n" ); + } + if ( badFrameIndicator != 0 && badFrameIndicator != 1 ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "badFrameIndicator must be 1 or 0\n" ); + } + if ( badFrameIndicator == 0 && bitstream_in_size <= 0 ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "bitstream_in_size must be positive\n" ); + } + + if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + config_num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; + if ( !badFrameIndicator ) + { + if ( LC3PLUS_RTP_payload_deserialize( &payload, bitstream_in, bitstream_in_size ) != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + if ( payload.sampling_rate_hz != handle->config.samplerate ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (samplerate) in bitstream is not supported\n" ); + } + if ( payload.num_channels != handle->config.channels ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (number of channels) in bitstream is not supported\n" ); + } + if ( payload.frame_duration_us != handle->config.lc3plus_frame_duration_us ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (frame duration) in bitstream is not supported\n" ); + } + if ( payload.high_resolution_enabled != handle->config.high_res_mode_enabled ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (high resolution mode) in bitstream is not supported\n" ); + } + if ( payload.num_media_times != config_num_media_times ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "LC3plus config change (number of media times per frame data block) in bitstream is not supported\n" ); + } + } +#endif + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / config_num_media_times ); + for ( iDec = 0; iDec < handle->num_decs; iDec++ ) + { + for ( iMediaTime = 0; iMediaTime < config_num_media_times; iMediaTime++ ) + { + iFtd = iDec + iMediaTime * handle->num_decs; +#else + lc3framesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; + + numSamplesPerLC3plusChannel = (int16_t) ( handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / lc3framesPerIvasFrame ); + bitstreamOffsetPerCoder = bitstream_in_size / handle->num_decs / lc3framesPerIvasFrame; + for ( iDec = 0; iDec < handle->num_decs; iDec++ ) + { + for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ ) + { +#endif + if ( handle->selective_decoding_states[iDec]->shall_decode_cached_frame ) + { + if ( 0 == handle->bitstream_caches[iDec]->bitstream_cache_size ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "LC3plus cache is empty\n" ); + } + + err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], handle->bitstream_caches[iDec]->bitstream_cache, handle->bitstream_caches[iDec]->bitstream_cache_size, &handle->pcm_conversion_buffer, badFrameIndicator, handle->scratch ); + if ( err != IVAS_ERR_OK ) + { + return IVAS_ERROR( err, "lc3plus decoding failed\n" ); + } + handle->selective_decoding_states[iDec]->shall_decode_cached_frame = 0; + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0; + } + + /* reset cache if caching is enabled - it has either been decoded or is not needed */ + if ( NULL != handle->bitstream_caches ) + { + handle->bitstream_caches[iDec]->bitstream_cache_size = 0; + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + switch ( handle->selective_decoding_states[iDec]->frame_action ) +#else + switch ( handle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] ) +#endif + { +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + case DEC_ACTION_DECODE_AND_DROP: + { + err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator, handle->scratch ); + if ( err != IVAS_ERR_OK ) + { + return IVAS_ERROR( err, "lc3plus decoding failed\n" ); + } + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0; + break; + } +#endif + case DEC_ACTION_DECODE_AND_USE: + { +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( badFrameIndicator ) + { + err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in, bitstream_in_size, &handle->pcm_conversion_buffer, badFrameIndicator, handle->scratch ); + } + else if ( payload.ftds[iFtd].frame_data_length == LC3PLUS_RTP_FDL_SPEECH_BAD ) + { + return IVAS_ERR_NOT_IMPLEMENTED; + /* Untested therefore disabled. Would probably only need to call concealment, + * but the LC3plus API requires a non-NULL ptr for this which is not available here */ + } + else + { + err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], payload.ftds[iFtd].frame_data, payload.ftds[iFtd].frame_data_length, &handle->pcm_conversion_buffer, badFrameIndicator, handle->scratch ); + } + if ( err != IVAS_ERR_OK ) + { + return IVAS_ERROR( err, "lc3plus decoding failed\n" ); + } + + for ( int16_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ ) + { + ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel; + pcm_out[iDec][ivasSampleIndex] = handle->pcm_conversion_buffer[iSampleInt16]; + } + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0; + break; +#else + err = decode_or_conceal_one_lc3plus_frame( handle->handles[iDec], bitstream_in_iter, bitstreamOffsetPerCoder, &handle->pcm_conversion_buffer, badFrameIndicator ); + if ( err != IVAS_ERR_OK ) + { + return IVAS_ERROR( err, "lc3plus decoding failed\n" ); + } + + for ( int32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ ) + { + ivasSampleIndex = iSampleInt16 + iLc3plusFrame * numSamplesPerLC3plusChannel; + pcm_out[iDec][ivasSampleIndex] = handle->pcm_conversion_buffer[iSampleInt16]; + } + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 0; + break; +#endif + } +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + case DEC_ACTION_SKIP: + { + /* log that this instance has skipped a frame and must decode twice once reactivated */ + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1; + break; + } +#endif + case DEC_ACTION_CACHE: + { +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < (int32_t) payload.ftds[iFtd].frame_data_length ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" ); + } + /* store bit rate of cached frame */ + mvc2c( payload.ftds[iFtd].frame_data, handle->bitstream_caches[iDec]->bitstream_cache, (int16_t) payload.ftds[iFtd].frame_data_length ); + handle->bitstream_caches[iDec]->bitstream_cache_size = payload.ftds[iFtd].frame_data_length; + /* log that this instance has skipped a frame and must decode twice once reactivated */ + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1; + break; +#else + if ( handle->bitstream_caches[iDec]->bitstream_cache_capacity < bitstreamOffsetPerCoder ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "bitstream_cache_capacity is too low for LC3plus frame size\n" ); + } + /* store bit rate of cached frame */ + mvc2c( bitstream_in_iter, handle->bitstream_caches[iDec]->bitstream_cache, (int16_t) bitstreamOffsetPerCoder ); + handle->bitstream_caches[iDec]->bitstream_cache_size = bitstreamOffsetPerCoder; + /* log that this instance has skipped a frame and must decode twice once reactivated */ + handle->selective_decoding_states[iDec]->has_skipped_a_frame = 1; + break; +#endif + } + case DEC_ACTION_NUM_ENUMS: + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "invalid LC3plus decoder state\n" ); + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + } /* for each media time */ + /* reset skipping state, must be set by the user before each decode call*/ + handle->selective_decoding_states[iDec]->frame_action = DEC_ACTION_DECODE_AND_USE; + } /* for each dec/channel */ +#else + + bitstream_in_iter += bitstreamOffsetPerCoder; + } + + /* reset skipping state, must be set by the user before each decode call*/ + for ( iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ ) + { + handle->selective_decoding_states[iDec]->frame_actions[iLc3plusFrame] = DEC_ACTION_DECODE_AND_USE; + } + } + +#endif + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_Decode() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_DEC_Decode( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder configuration */ + uint8_t *bitstream_in, /* i : pointer to input bitstream */ + const int32_t bitstream_in_size, /* i : size of bitstream_in */ + Word32 **pcm_out /* o : decoded samples */ +) +{ + int16_t badFrameIndicator; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Dec_Wrap_Handle is NULL\n" ); + } + if ( NULL == bitstream_in ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_in is NULL\n" ); + } + if ( NULL == pcm_out ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_out is NULL\n" ); + } + badFrameIndicator = 0; + + return isar_LC3PLUS_DEC_Decode_or_Conceal_internal( handle, bitstream_in, bitstream_in_size, badFrameIndicator, pcm_out ); +} + + +/*------------------------------------------------------------------------- + * ISAR_LC3PLUS_DEC_Conceal() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_DEC_Conceal( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : LC3plus decoder handle */ + Word32 **pcm_out /* o : decoded samples */ +) +{ + uint8_t bitstream_in[LC3PLUS_MAX_BYTES]; + int16_t badFrameIndicator; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Dec_Wrap_Handle is NULL\n" ); + } + + if ( NULL == pcm_out ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_out is NULL\n" ); + } + + /* LC3plus API requires a non-NULL bitstream pointer, even when triggering concealment */ + badFrameIndicator = 1; + + return isar_LC3PLUS_DEC_Decode_or_Conceal_internal( handle, bitstream_in, 0, badFrameIndicator, pcm_out ); +} +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/lib_isar/isar_lc3plus_dec.h b/lib_isar/isar_lc3plus_dec.h new file mode 100644 index 000000000..309ec4e06 --- /dev/null +++ b/lib_isar/isar_lc3plus_dec.h @@ -0,0 +1,136 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_LC3PLUS_DEC_H +#define ISAR_LC3PLUS_DEC_H + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "lc3.h" +#include "ivas_error.h" +#include "ivas_cnst.h" +#include "isar_lc3plus_common.h" + + +typedef enum +{ +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + DEC_ACTION_DECODE_AND_DROP = 0, +#endif + DEC_ACTION_DECODE_AND_USE, +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + DEC_ACTION_SKIP, +#endif + DEC_ACTION_CACHE, + DEC_ACTION_NUM_ENUMS +} SelectiveDecAction; + + +typedef struct ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE +{ + /*! indicates that the decoder has skipped one or more frames. This means it must decode two frames to flush algorithmic delay when re-activated */ + int16_t has_skipped_a_frame; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /*! action to execute for the next frame */ + SelectiveDecAction frame_action; +#else + /*! if set to 1, decoder will skip decoding for the next frame */ + SelectiveDecAction *frame_actions; +#endif + /*! if set to 1, decoder will decode the cache before decoding any of current frames */ + int16_t shall_decode_cached_frame; +} ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE; + +typedef struct ISAR_LC3PLUS_DEC_BITSTREAM_CACHE +{ + uint8_t *bitstream_cache; + int32_t bitstream_cache_capacity; + int32_t bitstream_cache_size; +} ISAR_LC3PLUS_DEC_BITSTREAM_CACHE; + +/* decoder wrapper */ +typedef struct ISAR_LC3PLUS_DEC_HANDLE +{ + LC3PLUS_Dec **handles; + ISAR_LC3PLUS_DEC_SELECTIVE_DECODING_STATE **selective_decoding_states; + ISAR_LC3PLUS_DEC_BITSTREAM_CACHE **bitstream_caches; + uint32_t num_decs; + int16_t *pcm_conversion_buffer; + uint8_t *scratch; + LC3PLUS_CONFIG config; +} * ISAR_LC3PLUS_DEC_HANDLE; + +ivas_error ISAR_LC3PLUS_DEC_Open( + const LC3PLUS_CONFIG config, /* i : decoder configuration */ + ISAR_LC3PLUS_DEC_HANDLE *handle /* o : decoder handle */ +); + +ivas_error ISAR_LC3PLUS_DEC_GetDelay( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ + int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */ +); + +void ISAR_LC3PLUS_DEC_Close( + ISAR_LC3PLUS_DEC_HANDLE *handle /* i/o: pointer to decoder handle */ +); + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +/*! Sets a matrix[MAX_PARAM_SPATIAL_SUBFRAMES][numLC3plusDecoders] where all require subframes must be flagged with 1, frames that are not required with 0 */ +ivas_error ISAR_LC3PLUS_DEC_SetSelectiveDecodingMatrix( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ + int16_t *subframeChannelMatrix[MAX_PARAM_SPATIAL_SUBFRAMES] /* i : */ +); +#endif + +ivas_error ISAR_LC3PLUS_DEC_Decode( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ + uint8_t *bitstream_in, /* i : pointer to input bitstream */ + const int32_t bitstream_in_size, /* i : size of bitstream_in */ + Word32 **pcm_out /* o : decoded samples */ +); + +ivas_error ISAR_LC3PLUS_DEC_Conceal( + ISAR_LC3PLUS_DEC_HANDLE handle, /* i : decoder handle */ + Word32 **pcm_out /* o : decoded samples */ +); + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +ivas_error ISAR_LC3PLUS_DEC_AllocateSubframeDecodingMatrix( + int16_t ***subframeChannelMatrix, + const uint32_t num_decs ); + +void isar_LC3PLUS_DEC_FreeSubframeDecodingMatrix( int16_t **subframeChannelMatrix ); +#endif + +#endif /* SPLIT_REND_WITH_HEAD_ROT */ +#endif /* ISAR_LC3PLUS_DEC_H */ diff --git a/lib_isar/isar_lc3plus_enc.c b/lib_isar/isar_lc3plus_enc.c new file mode 100644 index 000000000..f6bb0284d --- /dev/null +++ b/lib_isar/isar_lc3plus_enc.c @@ -0,0 +1,697 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include "isar_lc3plus_enc.h" +#include "isar_lc3plus_common.h" +#include "lc3.h" +#include "ivas_error_utils.h" +#include "prot.h" +#include "wmc_auto.h" +#include "options.h" + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +static const LC3PLUS_RTP_FDL s_fdl_request = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA; +#endif + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +static int32_t limit_per_channel_bitrate( LC3PLUS_CONFIG config, + int32_t per_channel_bitrate ) +{ + if ( config.high_res_mode_enabled ) + { + switch ( config.lc3plus_frame_duration_us ) + { + case 10000: + return min( per_channel_bitrate, 500000 ); + case 5000: + return min( per_channel_bitrate, 600000 ); + case 2500: + return min( per_channel_bitrate, 672000 ); + default: + assert( false && "unreachable" ); + } + } + + switch ( config.samplerate ) + { + case 48000: + case 32000: + return min( per_channel_bitrate, 320000 ); + case 24000: + return min( per_channel_bitrate, 314400 ); + case 16000: + return min( per_channel_bitrate, 221600 ); + case 8000: + return min( per_channel_bitrate, 114400 ); + default: + assert( false && "unreachable" ); + } + + assert( false && "unreachable" ); + return -1; +} +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-------------------------------------------------------------------* + * Function ISAR_LC3PLUS_ENC_Open() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_LC3PLUS_ENC_Open( + const LC3PLUS_CONFIG config, /* i : LC3plus encoder configuration */ + const UWord32 bitsPerSecond, /* i : bit rate */ + ISAR_LC3PLUS_ENC_HANDLE *handle /* o : encoder handle */ +) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t num_lc3plus_media_times_per_ivas_frame; +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t lc3plus_num_bytes_per_frame; +#endif + bool is_last_media_time, is_last_channel; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ivas_error ivas_err; +#endif +#endif +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t bitsPerSecondPerChannel; +#endif + Word32 scratch_size; + int32_t encoder_size; + LC3PLUS_Error err; + int32_t lfeChans[1]; + int16_t i; + + lfeChans[0] = 0; + + if ( 0U == config.channels ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" ); + } +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + bitsPerSecondPerChannel = bitsPerSecond / config.channels; +#endif +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" ); + } + if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" ); + } +#endif + encoder_size = lc3plus_enc_get_size( config.samplerate, 1 ); + if ( 0 == encoder_size ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" ); + } + + if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *handle )->config = config; + ( *handle )->frame_type_descriptors = NULL; +#endif + + ( *handle )->pcm_conversion_buffer = NULL; + ( *handle )->num_encs = 0; + if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" ); + } + + for ( i = 0; i < config.channels; ++i ) + { + ( *handle )->handles[i] = NULL; + } + ( *handle )->num_encs = config.channels; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us; + ( *handle )->fdl_request = s_fdl_request; + ( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame; + ( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) ); + if ( NULL == ( *handle )->frame_type_descriptors ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" ); + } +#endif + + for ( int32_t iCh = 0; iCh < config.channels; iCh++ ) + { + if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans ); +#else + err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, 0, lfeChans ); +#endif + if ( err != LC3PLUS_OK ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" ); + } + + err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 ); + if ( err != LC3PLUS_OK ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" ); + } +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + err = lc3plus_enc_set_bitrate( ( *handle )->handles[iCh], bitsPerSecondPerChannel ); + if ( err != LC3PLUS_OK ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" ); + } +#endif + } + + if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" ); + } + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *handle )->config = config; +#endif + ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 ); + if ( NULL == ( *handle )->pcm_conversion_buffer ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* update FDI fields */ + for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime ) + { + for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc ) + { + int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */ +#else + lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( ( *handle )->handles[iEnc] ); + if ( lc3plus_num_bytes_per_frame <= 0 ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" ); + } + ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = lc3plus_num_bytes_per_frame; +#endif + if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" ); + } + if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" ); + } + ( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY; + ( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL; + + /* The FTDs in the ToC are included in the following order: + * 1) First the FTD for the first channel of the first FDB (oldest frame) + * 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order + * 3) Then the FTD for the first channel of the second FDB + * 4) Then the FTDs for the remaining channels for the second FDB + * 5) Etc. to the last FDB */ + is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime; + is_last_channel = ( *handle )->num_encs - 1 == iEnc; + if ( is_last_media_time && is_last_channel ) + { + ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + } + else if ( !is_last_media_time && is_last_channel ) + { + ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + } + else + { + ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + } + } + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond ); + if ( ivas_err != IVAS_ERR_OK ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return ivas_err; + } +#endif +#endif + scratch_size = lc3plus_enc_get_scratch_size( ( *handle )->handles[0] ); + ( *handle )->scratch = malloc( sizeof( uint8_t ) * scratch_size ); + IF( NULL == ( *handle )->scratch ) + { + ISAR_LC3PLUS_ENC_Close( handle ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper scratch\n" ); + } + + return IVAS_ERR_OK; +} + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +/*-------------------------------------------------------------------* + * Function IVAS_LC3PLUS_ENC_SetBitrate() + * + * + *-------------------------------------------------------------------*/ + +ivas_error IVAS_LC3PLUS_ENC_SetBitrate( + ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */ + const uint32_t bitsPerSecond /* i : new target bit rate */ +) +{ + int32_t numLc3plusMediaTimesPerIvasFrame; + int32_t lc3plus_num_bytes_per_frame; + int32_t availableOctetsPerIsarFrame; + int32_t actualOctetsPerFrame; + LC3PLUS_Error err; + int32_t iFtd; + int32_t fdrLength; + int32_t lc3plusPacketRate; + int32_t numSubframes; + int32_t minPayloadOverhead; + int32_t targetLc3PlusBitratePerChannel; + int32_t targetLc3PlusOctetCount; + int32_t lc3plusFdlLength; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" ); + } + + availableOctetsPerIsarFrame = bitsPerSecond / ( 1000000 / handle->config.isar_frame_duration_us ) / 8; + lc3plusPacketRate = 1000 * 1000 / handle->config.lc3plus_frame_duration_us; + numLc3plusMediaTimesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; + numSubframes = numLc3plusMediaTimesPerIvasFrame * handle->config.channels; + + /* subtract minimum required payload bytes & calculate a first per-channel target bit rate */ + if ( LC3PLUS_RTP_frame_data_length_get_size( &fdrLength, s_fdl_request ) != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" ); + } + minPayloadOverhead = fdrLength + ( numSubframes * LC3PLUS_RTP_FTD_MIN_SIZE ); + targetLc3PlusBitratePerChannel = ( availableOctetsPerIsarFrame - minPayloadOverhead ) / handle->config.channels * 8 * lc3plusPacketRate / numLc3plusMediaTimesPerIvasFrame; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( targetLc3PlusBitratePerChannel <= 0 ) + { + return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" ); + } +#endif + targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel ); + targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate; + /* check resulting octet count. If it requires larger than 1-byte length fields, decrease the bitrate by enough to make room for the additional length field */ + if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" ); + } + if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH ) + { + /* reduce bitrate to allow for the required fdl field */ + targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate; + } + + for ( int32_t iCh = 0; iCh < handle->config.channels; iCh++ ) + { + err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel ); + if ( err != LC3PLUS_OK ) + { + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" ); + } + } + + // update FTD settings after bitrate change + for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime ) + { + for ( uint32_t iEnc = 0; iEnc < handle->num_encs; ++iEnc ) + { + iFtd = iEnc + iMediaTime * handle->num_encs; + lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] ); + if ( lc3plus_num_bytes_per_frame <= 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" ); + } + handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame; + } + } + + // TODO: remove sanity checks? + if ( ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "ISAR_LC3PLUS_ENC_GetOutputBitstreamSize failed\n" ); + } + if ( actualOctetsPerFrame > availableOctetsPerIsarFrame ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" ); + } + return IVAS_ERR_OK; +} +#endif + + +/*-------------------------------------------------------------------* + * Function ISAR_LC3PLUS_ENC_GetDelay() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_ENC_GetDelay( + ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ + int32_t *delayInSamples /* o : encoder delay in number of samples per channel */ +) +{ + int32_t tmpDelayInSamples; + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" ); + } + if ( NULL == delayInSamples ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "delayInSamples is NULL\n" ); + } + + *delayInSamples = 0; + /* sanity check whether all encoders are actually configured identically */ + for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ ) + { + if ( NULL == handle->handles[iEnc] ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" ); + } + + tmpDelayInSamples = lc3plus_enc_get_delay( handle->handles[iEnc] ); + if ( 0 != *delayInSamples && tmpDelayInSamples != *delayInSamples ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Not all mono LC3plus encoders are configured identically\n" ); + } + *delayInSamples = tmpDelayInSamples; + } + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * Function ISAR_LC3PLUS_ENC_GetOutputBitstreamSize() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( + ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ + Word32 *bsSize /* o : size of each bitstream frame in bytes */ +) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_RTP_ERR rtp_err; + int32_t num_lc3plus_media_times_per_ivas_frame; + int32_t iMediaTime; + int32_t ftd_frame_data_length_size, lc3plus_frame_data_length; + int32_t ftd_index; +#else + int32_t bitstreamSizeMultiplier; +#endif + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" ); + } + if ( NULL == bsSize ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( 0 == handle->config.lc3plus_frame_duration_us ) + { + return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" ); + } + if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); + } + + num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; +#endif + *bsSize = 0; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t fdl_request_length; + rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request ); + if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" ); + } + *bsSize += fdl_request_length; +#endif + for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ ) + { + if ( NULL == handle->handles[iEnc] ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" ); + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] ); + for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime ) + { + ftd_index = iEnc + iMediaTime * handle->num_encs; + if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" ); + } + rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length ); + if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" ); + } + *bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL; + *bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length; + *bsSize += ftd_frame_data_length_size; + } + } +#else + *bsSize += lc3plus_enc_get_num_bytes( handle->handles[iEnc] ); + } + + if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); + } + bitstreamSizeMultiplier = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; + + *bsSize *= bitstreamSizeMultiplier; +#endif + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * Function ISAR_LC3PLUS_ENC_Close() + * + * + *-------------------------------------------------------------------*/ + +void ISAR_LC3PLUS_ENC_Close( + ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */ +) +{ + if ( NULL == handle || NULL == *handle ) + { + return; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( NULL != ( *handle )->frame_type_descriptors ) + { + free( ( *handle )->frame_type_descriptors ); + } +#endif + for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ ) + { + if ( NULL != ( *handle )->handles[iEnc] ) + { + free( ( *handle )->handles[iEnc] ); + } + } + if ( NULL != ( *handle )->pcm_conversion_buffer ) + { + free( ( *handle )->pcm_conversion_buffer ); + } + + if ( NULL != ( *handle )->scratch ) + { + free( ( *handle )->scratch ); + } + + free( ( *handle )->handles ); + free( *handle ); + + *handle = NULL; + + return; +} + + +/*-------------------------------------------------------------------* + * Function ISAR_LC3PLUS_ENC_Encode() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_LC3PLUS_ENC_Encode( + ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ + Word32 **pcm_in, /* i : pointer input samples */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + void *bitstream_out, /* o : pointer to bitstream frame */ + const Word32 bitstream_out_size, /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */ +#else + void *bitstream_out /* o : pointer to bitstream frame */ +#endif + Word16 q_in[16] ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t ftdIndex; + LC3PLUS_RTP_ERR rtpErr; + uint32_t num_media_times; +#else + uint32_t lc3framesPerIvasFrame; + uint8_t *bitstream_out_iter = bitstream_out; +#endif + uint32_t numSamplesPerLC3plusChannel; + int32_t ivasSampleIndex; + int32_t num_bytes = 0; + LC3PLUS_Error err; + + push_wmops( "ISAR_LC3PLUS_ENC_Encode" ); + + if ( NULL == handle ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" ); + } + if ( NULL == pcm_in ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_in is NULL\n" ); + } + if ( NULL == bitstream_out ) + { + return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" ); + } + + if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 ) + { + return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" ); + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; + numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times; + + size_t actual_size; + rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds ); + if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } +#else + lc3framesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us; + + numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / lc3framesPerIvasFrame; +#endif + for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ ) + { +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + for ( uint32_t iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ ) +#else + for ( uint32_t iLc3plusFrame = 0; iLc3plusFrame < lc3framesPerIvasFrame; iLc3plusFrame++ ) +#endif + { + for ( uint32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ ) + { +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel; +#else + ivasSampleIndex = iSampleInt16 + iLc3plusFrame * numSamplesPerLC3plusChannel; +#endif + handle->pcm_conversion_buffer[iSampleInt16] = (Word16) max( INT16_MIN, min( L_shr( pcm_in[iEnc][ivasSampleIndex], q_in[iEnc] ), INT16_MAX ) ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ftdIndex = iMediaTime * handle->num_encs + iEnc; +#endif + num_bytes = 0; + push_wmops( "lc3plus_enc16" ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, handle->scratch ); +#else + err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, bitstream_out_iter, &num_bytes, NULL ); +#endif + pop_wmops(); + if ( err != LC3PLUS_OK ) + { + return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" ); + } + if ( 0 == num_bytes ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" ); + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" ); + } +#else + + bitstream_out_iter += num_bytes; +#endif + } + } + + pop_wmops(); + + return IVAS_ERR_OK; +} +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/lib_isar/isar_lc3plus_enc.h b/lib_isar/isar_lc3plus_enc.h new file mode 100644 index 000000000..a2bc10bfc --- /dev/null +++ b/lib_isar/isar_lc3plus_enc.h @@ -0,0 +1,104 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_LC3PLUS_ENC_H +#define ISAR_LC3PLUS_ENC_H + +#include +#include "ivas_error.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "lc3.h" +#include "isar_lc3plus_common.h" +#include "typedef.h" +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#include "isar_lc3plus_payload.h" +#endif + +/* encoder wrapper */ +typedef struct ISAR_LC3PLUS_ENC_HANDLE +{ + LC3PLUS_CONFIG config; + LC3PLUS_Enc **handles; + uint32_t num_encs; + int16_t *pcm_conversion_buffer; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_RTP_FTD *frame_type_descriptors; + int32_t num_ftds; + LC3PLUS_RTP_FDL fdl_request; +#endif + uint8_t *scratch; +} * ISAR_LC3PLUS_ENC_HANDLE; + +ivas_error ISAR_LC3PLUS_ENC_Open( + const LC3PLUS_CONFIG config, /* i : encoder configuration */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const uint32_t initialBitsPerSecond, /* i : initial target bit rate */ +#else + const uint32_t bitsPerSecond, /* i : bit rate */ +#endif + ISAR_LC3PLUS_ENC_HANDLE *handle /* o : LC3plus encoder handle */ +); + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +ivas_error IVAS_LC3PLUS_ENC_SetBitrate( + ISAR_LC3PLUS_ENC_HANDLE handle, /* o : LC3plus encoder handle */ + const uint32_t bitsPerSecond /* i : new target bit rate */ +); +#endif + +ivas_error ISAR_LC3PLUS_ENC_GetDelay( + ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ + int32_t *delayInSamples /* o : algorithmic delay of encoding and decoding in number of samples per channel */ +); + +ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( + ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ + int32_t *bsSize /* o : size of next bitstream frame in bytes */ +); + +void ISAR_LC3PLUS_ENC_Close( + ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle */ +); + +ivas_error ISAR_LC3PLUS_ENC_Encode( + ISAR_LC3PLUS_ENC_HANDLE handle, /* i : LC3plus encoder handle */ + Word32 **pcm_in, /* i : pointer input samples */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + void *bitstream_out, /* o : pointer to bitstream frame */ + const Word32 bitstream_out_size, /* i : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */ +#else + void *bitstream_out /* o : pointer to bitstream frame */ +#endif + Word16 q_in[16] ); +#endif + +#endif /* ISAR_LC3PLUS_ENC_H */ diff --git a/lib_isar/isar_lc3plus_payload.c b/lib_isar/isar_lc3plus_payload.c new file mode 100644 index 000000000..fa47189ca --- /dev/null +++ b/lib_isar/isar_lc3plus_payload.c @@ -0,0 +1,823 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include +#include +#include "isar_lc3plus_payload.h" +#include "options.h" + +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +static LC3PLUS_RTP_ERR s_frame_duration_ms_from_fdi( int32_t *frame_duration_us, const LC3PLUS_RTP_FTD_FDI fdi ) +{ + if ( NULL == frame_duration_us ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + switch ( fdi ) + { + case LC3PLUS_RTP_FTD_FDI_2500_US: + *frame_duration_us = 2500; + break; + case LC3PLUS_RTP_FTD_FDI_5000_US: + *frame_duration_us = 5000; + break; + case LC3PLUS_RTP_FTD_FDI_10000_US: + *frame_duration_us = 10000; + break; + case LC3PLUS_RTP_FTD_FDI_RESERVED: + default: + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +static LC3PLUS_RTP_ERR s_sampling_rate_hz_from_bwr( int32_t *sample_rate_hz, const LC3PLUS_RTP_FTD_BWR bwr ) +{ + if ( NULL == sample_rate_hz ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + switch ( bwr ) + { + case LC3PLUS_RTP_FTD_BWR_NB: + *sample_rate_hz = 8000; + break; + case LC3PLUS_RTP_FTD_BWR_WB: + *sample_rate_hz = 16000; + break; + case LC3PLUS_RTP_FTD_BWR_SSWB: + *sample_rate_hz = 24000; + break; + case LC3PLUS_RTP_FTD_BWR_SWB: + *sample_rate_hz = 32000; + break; + case LC3PLUS_RTP_FTD_BWR_FBCD: + *sample_rate_hz = 44100; + break; + case LC3PLUS_RTP_FTD_BWR_FB: + *sample_rate_hz = 48000; + break; + case LC3PLUS_RTP_FTD_BWR_FBHR: + *sample_rate_hz = 48000; + break; + case LC3PLUS_RTP_FTD_BWR_UBHR: + *sample_rate_hz = 96000; + break; + default: + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +static LC3PLUS_RTP_ERR s_high_resolution_flag_from_bwr( int16_t *high_resolution_flag, const LC3PLUS_RTP_FTD_BWR bwr ) +{ + if ( NULL == high_resolution_flag ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + switch ( bwr ) + { + case LC3PLUS_RTP_FTD_BWR_NB: + *high_resolution_flag = 0; + break; + case LC3PLUS_RTP_FTD_BWR_WB: + *high_resolution_flag = 0; + break; + case LC3PLUS_RTP_FTD_BWR_SSWB: + *high_resolution_flag = 0; + break; + case LC3PLUS_RTP_FTD_BWR_SWB: + *high_resolution_flag = 0; + break; + case LC3PLUS_RTP_FTD_BWR_FBCD: + *high_resolution_flag = 0; + break; + case LC3PLUS_RTP_FTD_BWR_FB: + *high_resolution_flag = 0; + break; + case LC3PLUS_RTP_FTD_BWR_FBHR: + *high_resolution_flag = 1; + break; + case LC3PLUS_RTP_FTD_BWR_UBHR: + *high_resolution_flag = 1; + break; + default: + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue ) +{ + if ( frameDataLengthValue == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_BAD || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_SID ) + { + *length = 1; + } + else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_1_MAX ) + { + *length = 1; + } + else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_2_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_2_MAX ) + { + *length = 2; + } + else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_3_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_3_MAX ) + { + *length = 3; + } + else + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +static LC3PLUS_RTP_ERR s_frame_data_length_pack( const LC3PLUS_RTP_FDL frameDataLengthValue, uint8_t *dst ) +{ + int32_t frame_data_length_size; + LC3PLUS_RTP_ERR err; + + if ( NULL == dst ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + + err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, frameDataLengthValue ); + if ( err != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return err; + } + if ( 1 == frame_data_length_size ) + { + *dst++ = frameDataLengthValue >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE; + } + else if ( 2 == frame_data_length_size ) + { + const int32_t frameDataLengthValueToWrite = frameDataLengthValue - LC3PLUS_RTP_FDL_EXTENSION_VALUE; + *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE; + *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE; + } + else if ( 3 == frame_data_length_size ) + { + const int32_t frameDataLengthValueToWrite = frameDataLengthValue - ( 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE ); + *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE; + *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE; + *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +static int32_t s_get_size_from_fdl( const LC3PLUS_RTP_FDL fdl ) +{ + if ( fdl >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl <= LC3PLUS_RTP_FDL_LENGTH_3_MAX ) + { + return fdl; + } + return 0; +} + +static bool s_fdl_is_magic_value( const LC3PLUS_RTP_FDL fdl ) +{ + if ( fdl == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || fdl == LC3PLUS_RTP_FDL_SPEECH_SID || fdl == LC3PLUS_RTP_FDL_SPEECH_BAD ) + { + return true; + } + return false; +} + +static bool s_fdl_value_is_valid_request( const LC3PLUS_RTP_FDL fdl_request ) +{ + /* LC3PLUS_RTP_FDL_SPEECH_SID && LC3PLUS_RTP_FDL_SPEECH_SID are not valid values for the FDL request */ + if ( fdl_request == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || ( fdl_request >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl_request <= LC3PLUS_RTP_FDL_LENGTH_3_MAX ) ) + { + return true; + } + return false; +} + +static LC3PLUS_RTP_ERR s_frame_data_length_parse( LC3PLUS_RTP_FDL *frame_data_length_value, const uint8_t *src, const size_t remaining_capacity ) +{ + int32_t frame_data_length_size; + LC3PLUS_RTP_ERR err; + if ( NULL == src || NULL == frame_data_length_value || remaining_capacity < 1 ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + + if ( remaining_capacity > 2 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *( src + 1 ) ) + { + *frame_data_length_value = *( src + 2 ) + 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE; + } + else if ( remaining_capacity > 1 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src ) + { + *frame_data_length_value = *( src + 1 ) + 1 * LC3PLUS_RTP_FDL_EXTENSION_VALUE; + } + else if ( remaining_capacity > 0 ) + { + *frame_data_length_value = *src << 0; + } + else + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + + /* sanity check */ + err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, *frame_data_length_value ); + if ( err != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return err; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +static LC3PLUS_RTP_ERR s_parse_ftd( const uint8_t *p_read, LC3PLUS_RTP_FTD *receiver_ftd, int32_t *num_bytes_read, const size_t remaining_capacity ) +{ + int32_t frame_data_block_size; + LC3PLUS_RTP_FDL fdl; + LC3PLUS_RTP_ERR err; + if ( NULL == p_read || NULL == receiver_ftd || NULL == num_bytes_read || remaining_capacity < LC3PLUS_RTP_FTD_MIN_SIZE ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + + *num_bytes_read = 0; + receiver_ftd->fc = 0; + receiver_ftd->fdi = 0; + receiver_ftd->bwr = 0; + receiver_ftd->h = 0; + receiver_ftd->fc |= *p_read & LC3PLUS_RTP_FTD_FC_MASK; + receiver_ftd->fdi |= ( *p_read & LC3PLUS_RTP_FTD_FDI_MASK ); + receiver_ftd->bwr |= ( *p_read & LC3PLUS_RTP_FTD_BWR_MASK ); + receiver_ftd->h |= ( *p_read & LC3PLUS_RTP_FTD_H_MASK ); + p_read++; + *num_bytes_read = 1; + + err = s_frame_data_length_parse( &fdl, p_read, remaining_capacity - *num_bytes_read ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + frame_data_block_size = s_get_size_from_fdl( fdl ); + + receiver_ftd->frame_data_length = frame_data_block_size; + int32_t length_field_size; + err = LC3PLUS_RTP_frame_data_length_get_size( &length_field_size, receiver_ftd->frame_data_length ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + *num_bytes_read += length_field_size; + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize( + uint8_t *serialized_buffer, + const size_t serialized_buffer_capacity, + size_t *packed_buffer_actual_size, + const LC3PLUS_RTP_FDL fdl_request, + LC3PLUS_RTP_FTD *sender_ftds, + const size_t sender_ftds_num ) +{ + LC3PLUS_RTP_ERR err; + uint8_t *p_write = serialized_buffer; + uint32_t i; + int32_t bytes_written = 0; + int32_t lc3plus_frame_size_sum; + uint8_t *p_frame_data; + int32_t fdl_request_length; + + if ( NULL == serialized_buffer || NULL == packed_buffer_actual_size || NULL == sender_ftds ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + + *packed_buffer_actual_size = 0; + err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, fdl_request ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( !s_fdl_value_is_valid_request( fdl_request ) ) + { + return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST; + } + if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_request_length ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + err = s_frame_data_length_pack( fdl_request, p_write ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + bytes_written += fdl_request_length; + p_write += bytes_written; + + for ( i = 0; i < sender_ftds_num; ++i ) + { + /* only the last ftd may have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */ + if ( sender_ftds[i].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i != ( sender_ftds_num - 1 ) ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + /* the last ftd must have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */ + if ( sender_ftds[i].fc != LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i == ( sender_ftds_num - 1 ) ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + if ( (int32_t) serialized_buffer_capacity < bytes_written + LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + *p_write = 0x00; + *p_write |= LC3PLUS_RTP_FTD_FC_MASK & (uint8_t) sender_ftds[i].fc; + *p_write |= LC3PLUS_RTP_FTD_FDI_MASK & (uint8_t) sender_ftds[i].fdi; + *p_write |= LC3PLUS_RTP_FTD_BWR_MASK & (uint8_t) sender_ftds[i].bwr; + *p_write |= LC3PLUS_RTP_FTD_H_MASK & (uint8_t) sender_ftds[i].h; + p_write++; + bytes_written += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL; + + int32_t fdl_length; + err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_length, sender_ftds[i].frame_data_length ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_length ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + err = s_frame_data_length_pack( sender_ftds[i].frame_data_length, p_write ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + p_write += fdl_length; + bytes_written += fdl_length; + } + + lc3plus_frame_size_sum = 0; + p_frame_data = serialized_buffer + bytes_written; + for ( i = 0; i < sender_ftds_num; ++i ) + { + sender_ftds[i].frame_data = p_frame_data; + p_frame_data += sender_ftds[i].frame_data_length; + lc3plus_frame_size_sum += sender_ftds[i].frame_data_length; + } + *packed_buffer_actual_size = bytes_written + lc3plus_frame_size_sum; + assert( *packed_buffer_actual_size <= serialized_buffer_capacity ); + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +static LC3PLUS_RTP_ERR s_ftds_parse( + LC3PLUS_RTP_FTD *receiver_ftds, + const int32_t receiver_ftds_num_max, + int16_t *receiver_ftds_num, + uint8_t *serialized_buffer, + const size_t serialized_buffer_size ) +{ + int32_t diff; + uint8_t *p_read; + uint32_t ftds_offset_sum = 0; + int16_t i; + LC3PLUS_RTP_ERR error; + int32_t frame_offset_counter; + int32_t size; + + p_read = serialized_buffer; + if ( NULL == receiver_ftds || NULL == receiver_ftds_num || NULL == serialized_buffer ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + if ( 0 == serialized_buffer_size ) + { + return LC3PLUS_RTP_ERR_EMPTY_TOC; + } + if ( receiver_ftds_num_max <= 0 ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + { + int32_t num_bytes_read_sum = 0; + const int32_t min_num_bytes_per_ftd = 2; + int16_t receiver_ftds_index = 0; + bool another_ftd = true; + int32_t num_bytes_read_per_ftd; + + while ( another_ftd ) + { + if ( (int32_t) serialized_buffer_size < min_num_bytes_per_ftd ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + if ( num_bytes_read_sum >= (int32_t) serialized_buffer_size - min_num_bytes_per_ftd ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + num_bytes_read_per_ftd = 0; + error = s_parse_ftd( p_read, &receiver_ftds[receiver_ftds_index], &num_bytes_read_per_ftd, serialized_buffer_size - num_bytes_read_sum ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != error ) + { + return error; + } + p_read += num_bytes_read_per_ftd; + num_bytes_read_sum += num_bytes_read_per_ftd; + + if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_RESERVED ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM; + } + else if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL ) + { + another_ftd = false; + } + + if ( another_ftd ) + { + if ( receiver_ftds_index >= receiver_ftds_num_max ) + { + return LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED; + } + ( receiver_ftds_index )++; + } + } + *receiver_ftds_num = receiver_ftds_index + 1; + } + + /* set frame-data pointers into serialized_buffer */ + for ( i = 0; i < *receiver_ftds_num; ++i ) + { + error = LC3PLUS_RTP_frame_data_length_get_size( &size, receiver_ftds[i].frame_data_length ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return error; + } + ftds_offset_sum += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + size; + } + + frame_offset_counter = 0; + for ( i = 0; i < *receiver_ftds_num; ++i ) + { + if ( s_fdl_is_magic_value( receiver_ftds[i].frame_data_length ) ) + { + receiver_ftds[i].frame_data = NULL; + } + else + { + receiver_ftds[i].frame_data = serialized_buffer + ftds_offset_sum + frame_offset_counter; + frame_offset_counter += receiver_ftds[i].frame_data_length; + } + } + + if ( ftds_offset_sum + frame_offset_counter != serialized_buffer_size ) + { + /* parsed content & size n bytes of input buffer do not line up */ + /* if the buffer capacity is larger and the remaining bytes are zero, we don't treat this as an error since it's due to the IVAS-Split rendering zero padding */ + diff = serialized_buffer_size - ( ftds_offset_sum + frame_offset_counter ); + if ( diff < 0 ) + { + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE; + } + /* verify that all bytes are zero */ + p_read += frame_offset_counter; + for ( i = 0; i < diff; ++i ) + { + if ( *p_read != 0 ) + { + /* non-zero byte in padding region */ + return LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES; + } + p_read++; + } + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize( + LC3PLUS_RTP_PAYLOAD *payload, + uint8_t *serialized_buffer, + const size_t serialized_buffer_size ) +{ + int32_t new_frame_duration_us; + int32_t new_sampling_rate_hz; + int16_t new_high_resolution_flag; + int16_t i = 0; + int16_t channel_id = 0; + int16_t media_time_id = 0; + const int16_t invalid_value = -1; + int16_t media_times_per_channel[LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS]; + int16_t channels_per_media_time[LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES]; + LC3PLUS_RTP_ERR err; + + if ( NULL == payload || NULL == serialized_buffer ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + if ( 0 == serialized_buffer_size ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + + for ( media_time_id = 0; media_time_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++media_time_id ) + { + channels_per_media_time[media_time_id] = invalid_value; + } + media_time_id = 0; + for ( channel_id = 0; channel_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++channel_id ) + { + media_times_per_channel[channel_id] = invalid_value; + } + channel_id = 0; + + err = s_frame_data_length_parse( &payload->fdl_request, serialized_buffer, serialized_buffer_size ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + int32_t fdl_request_length; + err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, payload->fdl_request ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( !s_fdl_value_is_valid_request( payload->fdl_request ) ) + { + return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST; + } + + err = s_ftds_parse( payload->ftds, sizeof( payload->ftds ) / sizeof( LC3PLUS_RTP_FTD ), &payload->num_ftds, serialized_buffer + fdl_request_length, serialized_buffer_size - fdl_request_length ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( 0 == payload->num_ftds ) + { + return LC3PLUS_RTP_ERR_GENERIC_ERROR; + } + /* verify shared setting between all FTDs [samplerate, frame_duration, channel count] */ + + /* initialize on the first FTD, use this as reference */ + err = s_frame_duration_ms_from_fdi( &payload->frame_duration_us, payload->ftds[0].fdi ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + err = s_sampling_rate_hz_from_bwr( &payload->sampling_rate_hz, payload->ftds[0].bwr ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + err = s_high_resolution_flag_from_bwr( &payload->high_resolution_enabled, payload->ftds[0].bwr ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + payload->num_channels = 0; + payload->num_media_times = 0; + for ( i = 0; i < payload->num_ftds; ++i ) + { + if ( payload->ftds[i].h != LC3PLUS_RTP_FTD_H_PRIMARY ) + { + /* not implemented */ + return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED; + } + + err = s_frame_duration_ms_from_fdi( &new_frame_duration_us, payload->ftds[i].fdi ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( payload->frame_duration_us != new_frame_duration_us ) + { + /* mixed frame durations not supported */ + return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION; + } + + err = s_sampling_rate_hz_from_bwr( &new_sampling_rate_hz, payload->ftds[i].bwr ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( payload->sampling_rate_hz != new_sampling_rate_hz ) + { + /* mixed sampling frequencies not supported */ + return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION; + } + + + err = s_high_resolution_flag_from_bwr( &new_high_resolution_flag, payload->ftds[i].bwr ); + if ( LC3PLUS_RTP_ERR_NO_ERROR != err ) + { + return err; + } + if ( payload->high_resolution_enabled != new_high_resolution_flag ) + { + /* mixed high resolution mode not supported */ + return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION; + } + + switch ( payload->ftds[i].fc ) + { + case LC3PLUS_RTP_FTD_FC_LAST_OVERALL: + channels_per_media_time[media_time_id]++; + media_times_per_channel[channel_id]++; + channel_id = 0; + media_time_id = 0; + break; + case LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL: + media_times_per_channel[channel_id]++; + channels_per_media_time[media_time_id]++; + channel_id++; + break; + case LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME: + media_times_per_channel[channel_id]++; + channels_per_media_time[media_time_id]++; + channel_id = 0; + media_time_id++; + break; + case LC3PLUS_RTP_FTD_FC_RESERVED: + default: + return LC3PLUS_RTP_ERR_INVALID_BITSTREAM; + } + } + + { + int32_t valid_num_media_times_per_channel; + int32_t iCh; + /* check whether all channels exist for each media time */ + if ( media_times_per_channel[0] == invalid_value ) + { + return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED; + } + valid_num_media_times_per_channel = media_times_per_channel[0]; + for ( iCh = 0; iCh < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++iCh ) + { + if ( media_times_per_channel[iCh] == invalid_value ) + { + break; + } + if ( valid_num_media_times_per_channel != media_times_per_channel[iCh] ) + { + return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED; + } + } + } + { + /* whether all media times exist for each channel */ + int32_t iMediaTime; + int32_t valid_num_channels_per_media_time; + if ( channels_per_media_time[0] == invalid_value ) + { + return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED; + } + valid_num_channels_per_media_time = channels_per_media_time[0]; + for ( iMediaTime = 0; iMediaTime < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++iMediaTime ) + { + if ( channels_per_media_time[iMediaTime] == invalid_value ) + { + break; + } + if ( valid_num_channels_per_media_time != channels_per_media_time[iMediaTime] ) + { + return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED; + } + } + } + + /* convert zero-index to count */ + payload->num_channels = channels_per_media_time[0] + 1; + payload->num_media_times = media_times_per_channel[0] + 1; + + /* verify that all media times have the same number of channels, partial packets are not supported */ + if ( payload->num_ftds != payload->num_channels * payload->num_media_times ) + { + return LC3PLUS_RTP_ERR_GENERIC_ERROR; + } + return LC3PLUS_RTP_ERR_NO_ERROR; +} + +LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled ) +{ + if ( NULL == bwr ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + switch ( sampling_rate ) + { + case 8000: + if ( high_res_enabled ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + *bwr = LC3PLUS_RTP_FTD_BWR_NB; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 16000: + if ( high_res_enabled ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + *bwr = LC3PLUS_RTP_FTD_BWR_WB; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 24000: + if ( high_res_enabled ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + *bwr = LC3PLUS_RTP_FTD_BWR_SSWB; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 32000: + if ( high_res_enabled ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + *bwr = LC3PLUS_RTP_FTD_BWR_SWB; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 44100: + if ( high_res_enabled ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + *bwr = LC3PLUS_RTP_FTD_BWR_FBCD; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 48000: + if ( 0 == high_res_enabled ) + { + *bwr = LC3PLUS_RTP_FTD_BWR_FB; + return LC3PLUS_RTP_ERR_NO_ERROR; + } + else + { + *bwr = LC3PLUS_RTP_FTD_BWR_FBHR; + return LC3PLUS_RTP_ERR_NO_ERROR; + } + case 96000: + if ( 0 == high_res_enabled ) + { + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; + } + *bwr = LC3PLUS_RTP_FTD_BWR_UBHR; + return LC3PLUS_RTP_ERR_NO_ERROR; + default: + break; + } + + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; +} + +LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us ) +{ + if ( NULL == fdi ) + { + return LC3PLUS_RTP_ERR_NULL_PTR; + } + switch ( frame_duration_us ) + { + case 2500: + *fdi = LC3PLUS_RTP_FTD_FDI_2500_US; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 5000: + *fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + return LC3PLUS_RTP_ERR_NO_ERROR; + case 10000: + *fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + return LC3PLUS_RTP_ERR_NO_ERROR; + default: + break; + } + + return LC3PLUS_RTP_ERR_INVALID_PARAMETERS; +} + +#endif /* ISAR_BITSTREAM_UPDATE_LC3PLUS */ +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/lib_isar/isar_lc3plus_payload.h b/lib_isar/isar_lc3plus_payload.h new file mode 100644 index 000000000..3af6757fa --- /dev/null +++ b/lib_isar/isar_lc3plus_payload.h @@ -0,0 +1,216 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_LC3PLUS_PAYLOAD_H +#define ISAR_LC3PLUS_PAYLOAD_H + +#include +#include +#include "lc3.h" +#include "options.h" + +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + +/* Implementation of the "B.2.6 Table of contents" part of the RTP payload format + * for LC3plus as specified in ETSI TS 103 634. */ + +typedef enum LC3PLUS_RTP_ERR +{ + LC3PLUS_RTP_ERR_NO_ERROR, + LC3PLUS_RTP_ERR_NULL_PTR, + LC3PLUS_RTP_ERR_INVALID_PARAMETERS, + LC3PLUS_RTP_ERR_EMPTY_TOC, + LC3PLUS_RTP_ERR_NOT_IMPLEMENTED, + LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION, + LC3PLUS_RTP_ERR_INVALID_BITSTREAM, + LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE, + LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED, + LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST, + LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES, + LC3PLUS_RTP_ERR_GENERIC_ERROR +} LC3PLUS_RTP_ERR; + +/* + * The content of the FTD is shown in Figure B.6. + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |FC |FDI| BWR |H| FDL1 | (FDL2) | (FDL3) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/* FC (2 bits): + * Frame and Channel (FC) indicator for subsequent frame data (if available). The meaning of the FC + * indicator is shown in Table B.2. The FC value defines the media time stamp (in integer increments + * of TSI) and the channel counter (CC, starting from 1 for the first channel) for the subsequent + * FTD (if available). */ +typedef enum LC3PLUS_RTP_FTD_FC +{ + LC3PLUS_RTP_FTD_FC_LAST_OVERALL = 0x00, /* Last FDL in ToC, no FDL follows the current FDL */ + LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL = 0x01, /* The next FDL is for the next channel for the same media time */ + LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME = 0x02, /* The next FDL is for first channel for next media time, channel counter is reset */ + LC3PLUS_RTP_FTD_FC_RESERVED = 0x03, /* Reserved */ +} LC3PLUS_RTP_FTD_FC; +#define LC3PLUS_RTP_FTD_FC_MASK 0x03 + +/* FDI (2 bits): + * Frame Duration Index, with encoding as shown in Table B.3. The FDI shall be static for a given + * payload type during the session. The FDI also dictates the TSI, needed for deriving the media + * time in case of more than one frame in the payload. */ +typedef enum LC3PLUS_RTP_FTD_FDI +{ + LC3PLUS_RTP_FTD_FDI_2500_US = 0x00, + LC3PLUS_RTP_FTD_FDI_5000_US = 0x04, + LC3PLUS_RTP_FTD_FDI_10000_US = 0x08, + LC3PLUS_RTP_FTD_FDI_RESERVED = 0x0C, +} LC3PLUS_RTP_FTD_FDI; +#define LC3PLUS_RTP_FTD_FDI_MASK 0x0C +LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us ); + +/* BWR (3 bits): + * Bandwidth and resolution combination used by the codec is jointly encoded into a bandwidth and + * resolution (BWR) index. The BWR index is encoded as shown in Table B.4. The BWR encoding is + * defined in Table B.4. The BWR index shall be static for a given payload type during the session. */ +typedef enum LC3PLUS_RTP_FTD_BWR +{ + LC3PLUS_RTP_FTD_BWR_NB = 0x00, + LC3PLUS_RTP_FTD_BWR_WB = 0x10, + LC3PLUS_RTP_FTD_BWR_SSWB = 0x20, + LC3PLUS_RTP_FTD_BWR_SWB = 0x30, + LC3PLUS_RTP_FTD_BWR_FBCD = 0x40, + LC3PLUS_RTP_FTD_BWR_FB = 0x50, + LC3PLUS_RTP_FTD_BWR_FBHR = 0x60, + LC3PLUS_RTP_FTD_BWR_UBHR = 0x70, +} LC3PLUS_RTP_FTD_BWR; +#define LC3PLUS_RTP_FTD_BWR_MASK 0x70 +LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled ); + +/* H (1 bit): + * Indicates whether the corresponding frame is a normal frame (primary encoding) or a helper frame + * (secondary encoding). 0 indicates a primary frame, 1 indicates secondary (redundant) frame */ +typedef enum LC3PLUS_RTP_FTD_H +{ + LC3PLUS_RTP_FTD_H_PRIMARY = 0x00, + LC3PLUS_RTP_FTD_H_SECONDARY = 0x80, +} LC3PLUS_RTP_FTD_H; +#define LC3PLUS_RTP_FTD_H_MASK 0x80 + +typedef enum LC3PLUS_RTP_FDL +{ + LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA = 0, + LC3PLUS_RTP_FDL_SPEECH_BAD = 1, + LC3PLUS_RTP_FDL_SPEECH_SID = 2, + LC3PLUS_RTP_FDL_RESERVED_MIN = 3, + LC3PLUS_RTP_FDL_RESERVED_MAX = 19, + LC3PLUS_RTP_FDL_LENGTH_1_MIN = 20, + LC3PLUS_RTP_FDL_LENGTH_1_MAX = 254, + LC3PLUS_RTP_FDL_LENGTH_2_MIN = 255, + LC3PLUS_RTP_FDL_LENGTH_2_MAX = 509, + LC3PLUS_RTP_FDL_LENGTH_3_MIN = 510, + LC3PLUS_RTP_FDL_LENGTH_3_MAX = 765 +} LC3PLUS_RTP_FDL; +/* value used to indicate that the Frame Data Length (FDL) extends to the next byte */ +#define LC3PLUS_RTP_FDL_EXTENSION_VALUE 0xFF + +typedef struct LC3PLUS_RTP_FTD +{ + LC3PLUS_RTP_FTD_FC fc; + LC3PLUS_RTP_FTD_FDI fdi; + LC3PLUS_RTP_FTD_BWR bwr; + LC3PLUS_RTP_FTD_H h; + uint8_t *frame_data; + LC3PLUS_RTP_FDL frame_data_length; +} LC3PLUS_RTP_FTD; +#define LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL 1 +#define LC3PLUS_RTP_FDL_MIN_LENGTH 1 +#define LC3PLUS_RTP_FTD_MIN_SIZE ( LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + LC3PLUS_RTP_FDL_MIN_LENGTH ) + +/*! Serialize the sender_ftds structs and fdl_request into a linear compact buffer + * @param[out] serialized_buffer pointer to the start of the memory location where the serialized buffer will be written to + * @param[in] serialized_buffer_capacity capacity of the serialized_buffer in bytes + * @param[out] packed_buffer_actual_size actually used size of in bytes of the packed_buffer (<=serialized_buffer_capacity) + * @param[in] fdl_request frame data length request + * @param[in,out] sender_ftds the function will overwrite the frame_data pointer with the correct memory location in + * the packed_buffer (so it can subsequently be used as input for the LC3plus encode call) + * @param[in] sender_ftds_num number of sender_ftds + * @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */ +LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize( + uint8_t *serialized_buffer, + const size_t serialized_buffer_capacity, + size_t *packed_buffer_actual_size, + const LC3PLUS_RTP_FDL fdl_request, + LC3PLUS_RTP_FTD *sender_ftds, + const size_t sender_ftds_num ); + +/*! Get size of the frame data length field for a certain frame data length value in bytes. + * @param[out] length size of the frame data length field in bytes [1,2,3] + * @param[in] frameDataLengthValue frame data length value + * @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */ +LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue ); + +#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS 16 +#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES 8 /* max ivas frame duration/min lc3plus frame duration: 20000/2500 */ +#define LC3PLUS_RTP_PAYLOAD_MAX_NUM_FTDS LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS *LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES + +typedef struct LC3PLUS_RTP_PAYLOAD_CONFIG +{ + /* frame duration in us shared among all FTDs */ + int32_t frame_duration_us; + /* high resolution flag shared among all FTDs */ + int16_t high_resolution_enabled; + /* sampling frequency shared among all FTDs */ + int32_t sampling_rate_hz; + /* number of individual channels in the payload */ + int16_t num_channels; + /* number of individual media times in the payload */ + int16_t num_media_times; + /* frame data length request */ + LC3PLUS_RTP_FDL fdl_request; + /* FTD data with pointer to raw frame data */ + LC3PLUS_RTP_FTD ftds[LC3PLUS_RTP_PAYLOAD_MAX_NUM_FTDS]; + /* actual number of ftds */ + int16_t num_ftds; +} LC3PLUS_RTP_PAYLOAD; + +/*! Deserialized a serialized buffer into a LC3PLUS_RTP_PAYLOAD struct + * @param payload pointer to target LC3PLUS_RTP_PAYLOAD object. Note: frame_data pointers in the struct will point to the respective memory locations in the serialized_buffer. + * @param serialized_buffer pointer to the start of the serialized input buffer + * @param serialized_buffer_size size of the serialized input buffer in bytes + * @return LC3PLUS_RTP_ERR_NO_ERROR in case of success */ +LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize( + LC3PLUS_RTP_PAYLOAD *payload, + uint8_t *serialized_buffer, + const size_t serialized_buffer_size ); + +#endif /* ISAR_BITSTREAM_UPDATE_LC3PLUS */ +#endif /* #ifdef SPLIT_REND_WITH_HEAD_ROT */ +#endif /* ISAR_LC3PLUS_PAYLOAD_H */ diff --git a/lib_isar/isar_lcld_decoder.c b/lib_isar/isar_lcld_decoder.c new file mode 100644 index 000000000..c067ad064 --- /dev/null +++ b/lib_isar/isar_lcld_decoder.c @@ -0,0 +1,1993 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "isar_lcld_prot.h" +#include "isar_lcld_rom_tables.h" +#include "prot.h" +#include +#include "isar_prot.h" +#include "wmc_auto.h" +#include "basop_util.h" +#include "prot_fx2.h" +// #define DEBUG_WRITE +#include "debug.h" +#include "enh64.h" + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + +#define HUFF_READ_SIZE ( 4 ) + +/*------------------------------------------------------------------------------------------* + * Local structures + *------------------------------------------------------------------------------------------*/ + +typedef struct TableNode +{ + struct TableNode **ppoNextTable; + struct TableNode *poOrderedNext; + + Word32 *piCodeIndex; + Word32 *piDifference; + Word32 *piLength; +} TableNode; + +typedef struct TableList +{ + TableNode *poOrderedTop; + TableNode *poOrderedBottom; + +} TableList; + +struct LCLD_DECODER +{ + Word32 iSampleRate; + Word32 iChannels; + Word32 iNumBlocks; + + Word32 iNumBands; + const Word32 *piBandwidths; + + Word32 iMSMode; + Word32 *piMSFlags; + TableList *ptable_list; + UWord32 ( *c_apauiHuffDecTable_RAM[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE]; + UWord32 num_decode_table[2 * ALLOC_TABLE_SIZE]; + Word32 piMSPredCoefs[MAX_BANDS]; + Word32 piLRPhaseDiffs[MAX_BANDS]; + Word32 iCommonGrouping; + Word32 *piNumGroups; + Word32 **ppiGroupLengths; + + Word32 ***pppiRMSEnvelope; + Word32 ***pppiSMR; + Word32 ***pppiExcitation; + Word32 ***pppiAlloc; + + Word32 iAllocOffset; + Word32 iRealOnlyOut; + + Word32 ***pppiLCLDSignReal; + Word32 ***pppiLCLDSignImag; + Word32 ***pppiQLCLDReal; + Word32 ***pppiQLCLDImag; + + PredictionDecoder *psPredictionDecoder; + + + NoiseGen *psNoiseGen; +}; + +static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, Word32 num, const UWord16 ( *ppuiEncTable )[2], Word32 iSize, Word32 iReadLength, UWord32 *iTables ); +static TableNode *CreateTableList( Word32 iReadLength ); +static void DeleteTableList( TableList *ptable_list, Word32 iTables ); +static TableNode *GetNextTable( Word32 iIndex, TableList *table_list, TableNode *poParent, Word32 iReadLength, UWord32 *iTablesCreated ); +static void AddcodeTableList( TableList *ptable_list, Word32 iLength, Word32 iCode, Word32 iCodeIndex, Word32 iReadLength, UWord32 *iTables ); +static void CompleteTables( LCLDDecoder *psLCLDDecoder, Word32 n, TableList *ptable_list, Word32 iReadLength, Word32 iTablesCreated ); + +static TableNode *CreateTableList( Word32 iReadLength ) +{ + Word32 n; + Word32 iMaxTables; + TableNode *ptable_top; + iMaxTables = L_shl( 1, (Word16) iReadLength ); + ptable_top = (TableNode *) malloc( sizeof( TableNode ) ); + ptable_top->ppoNextTable = + (TableNode **) malloc( iMaxTables * sizeof( TableNode * ) ); + ptable_top->piCodeIndex = (Word32 *) malloc( iMaxTables * sizeof( Word32 ) ); + ptable_top->piDifference = (Word32 *) malloc( iMaxTables * sizeof( Word32 ) ); + ptable_top->piLength = (Word32 *) malloc( iMaxTables * sizeof( Word32 ) ); + FOR( n = 0; n < iMaxTables; n++ ) + { + ptable_top->ppoNextTable[n] = NULL; + ptable_top->piCodeIndex[n] = 0xffff; + move32(); + ptable_top->piDifference[n] = 0; + move32(); + ptable_top->piLength[n] = 0; + move32(); + } + + return ptable_top; +} + +static void DeleteTableList( TableList *ptable_list, Word32 iTables ) +{ + + TableNode *node; + node = ptable_list->poOrderedTop; + + WHILE( ( iTables ) ) + { + + TableNode *node1 = node; + node = node1->poOrderedNext; + IF( node1->piCodeIndex != NULL ) + { + free( node1->piCodeIndex ); + } + IF( node1->piLength != NULL ) + { + free( node1->piLength ); + } + IF( node1->piDifference != NULL ) + { + free( node1->piDifference ); + } + IF( node1->ppoNextTable != NULL ) + { + free( node1->ppoNextTable ); + } + IF( node1 != NULL ) + { + free( node1 ); + } + iTables--; + } + IF( ptable_list != NULL ) + { + free( ptable_list ); + } +} + +static TableNode *GetNextTable( Word32 iIndex, TableList *table_list, TableNode *poParent, Word32 iReadLength, UWord32 *iTablesCreated ) +{ + TableNode *poNextNode; + + IF( poParent->ppoNextTable[iIndex] == NULL ) + { + poNextNode = CreateTableList( iReadLength ); + poParent->ppoNextTable[iIndex] = poNextNode; + poParent->piDifference[iIndex] = *iTablesCreated; /* this is a link to the next table rather than the difference */ + move32(); + table_list->poOrderedBottom->poOrderedNext = poNextNode; + table_list->poOrderedBottom = poNextNode; + + ( *iTablesCreated )++; + } + ELSE + { + poNextNode = poParent->ppoNextTable[iIndex]; + } + + return poNextNode; +} + +static void CompleteTables( LCLDDecoder *psLCLDDecoder, Word32 n, TableList *ptable_list, Word32 iReadLength, Word32 iTablesCreated ) +{ + + Word32 iMaxTables; + Word32 j; + TableNode *poNode; + + iMaxTables = L_shl( 1, (Word16) iReadLength ); + psLCLDDecoder->c_apauiHuffDecTable_RAM[n] = + malloc( iTablesCreated * iMaxTables * sizeof( UWord32 * ) ); + + poNode = ptable_list->poOrderedTop; + FOR( j = 0; j < iTablesCreated; j++ ) + { + Word32 k; + IF( poNode != NULL ) + { + FOR( k = 0; k < iMaxTables; k++ ) + { + UWord32 uiCode; + uiCode = poNode->piDifference[k]; + move32(); + uiCode = (UWord32) L_shl( (Word32) uiCode, 16 ); + uiCode = (UWord32) L_or( (Word32) uiCode, poNode->piCodeIndex[k] ); + psLCLDDecoder->c_apauiHuffDecTable_RAM[n][j][k] = uiCode; + move32(); + } + } + poNode = poNode->poOrderedNext; + } +} + +static void AddcodeTableList( TableList *ptable_list, Word32 iLength, Word32 iCode, Word32 iCodeIndex, Word32 iReadLength, UWord32 *iTables ) +{ + Word32 iDifference; + Word32 iMask; + Word32 iCurrentLength; + Word32 iIndex; + Word32 iCodeLow; + Word32 iCodeHigh; + + TableNode *poNode; + poNode = ptable_list->poOrderedTop; + iMask = L_sub( L_shl( 1, (Word16) iReadLength ), 1 ); + iCurrentLength = iLength; + move32(); + WHILE( GT_32( iCurrentLength, iReadLength ) ) + { + iDifference = L_sub( iCurrentLength, iReadLength ); + iIndex = L_shr( iCode, (Word16) iDifference ); + iIndex = L_and( iIndex, iMask ); + poNode = GetNextTable( iIndex, ptable_list, poNode, iReadLength, iTables ); + iCurrentLength = L_sub( iCurrentLength, iReadLength ); + } + + iMask = L_sub( L_shl( 1, (Word16) iCurrentLength ), 1 ); + iDifference = L_sub( iReadLength, iCurrentLength ); + iCodeLow = L_shl( L_and( iCode, iMask ), (Word16) iDifference ); + iMask = L_sub( L_shl( 1, (Word16) iDifference ), 1 ); + iCodeHigh = L_or( iCodeLow, iMask ); + FOR( iIndex = iCodeLow; iIndex <= iCodeHigh; iIndex++ ) + { + poNode->piCodeIndex[iIndex] = iCodeIndex; + move32(); + poNode->piDifference[iIndex] = iDifference; + move32(); + poNode->piLength[iIndex] = iLength; + move32(); + } +} + +static void CreateDecodeTable( LCLDDecoder *psLCLDDecoder, Word32 num, const UWord16 ( *ppuiEncTable )[2], Word32 iSize, Word32 iReadLength, UWord32 *iTables ) +{ + Word32 n; + UWord32 **ppsort_enc_table; + TableList *ptable_list; + ptable_list = (TableList *) malloc( sizeof( TableList ) ); + + ppsort_enc_table = (UWord32 **) malloc( iSize * sizeof( Word32 * ) ); + FOR( n = 0; n < iSize; n++ ) + { + ppsort_enc_table[n] = (UWord32 *) malloc( 3 * sizeof( Word32 ) ); + ppsort_enc_table[n][0] = (UWord32) ppuiEncTable[n][0]; + move32(); + ppsort_enc_table[n][1] = (UWord32) ppuiEncTable[n][1]; + move32(); + ppsort_enc_table[n][2] = (UWord32) n; + move32(); + } + + FOR( n = 0; n < iSize; n++ ) + { + UWord32 iMin; + Word32 iMinIndex; + Word32 k; + + iMin = ppsort_enc_table[n][0]; + move32(); + iMinIndex = n; + move32(); + FOR( k = n; k < iSize; k++ ) + { + IF( ppsort_enc_table[k][0] < iMin ) + { + iMin = ppsort_enc_table[k][0]; + move32(); + iMinIndex = k; + move32(); + } + } + + IF( NE_32( iMinIndex, n ) ) + { + UWord32 uiLength; + UWord32 uiCode; + UWord32 uiCodeIndex; + + uiLength = ppsort_enc_table[n][0]; + move32(); + uiCode = ppsort_enc_table[n][1]; + move32(); + uiCodeIndex = ppsort_enc_table[n][2]; + move32(); + + ppsort_enc_table[n][0] = ppsort_enc_table[iMinIndex][0]; + move32(); + ppsort_enc_table[n][1] = ppsort_enc_table[iMinIndex][1]; + move32(); + ppsort_enc_table[n][2] = ppsort_enc_table[iMinIndex][2]; + move32(); + + ppsort_enc_table[iMinIndex][0] = uiLength; + move32(); + ppsort_enc_table[iMinIndex][1] = uiCode; + move32(); + ppsort_enc_table[iMinIndex][2] = uiCodeIndex; + move32(); + } + } + ptable_list->poOrderedTop = CreateTableList( iReadLength ); + ptable_list->poOrderedBottom = ptable_list->poOrderedTop; + FOR( n = 0; n < iSize; n++ ) + { + Word32 iLength; + Word32 iCode; + Word32 iCodeIndex; + + iLength = ppsort_enc_table[n][0]; + move32(); + iCode = ppsort_enc_table[n][1]; + move32(); + iCodeIndex = ppsort_enc_table[n][2]; + move32(); + AddcodeTableList( ptable_list, iLength, iCode, iCodeIndex, iReadLength, + iTables ); + } + + CompleteTables( psLCLDDecoder, num, ptable_list, iReadLength, *iTables ); + DeleteTableList( ptable_list, *iTables ); + FOR( n = 0; n < iSize; n++ ) + { + free( ppsort_enc_table[n] ); + } + free( ppsort_enc_table ); +} + + +/*------------------------------------------------------------------------------------------* + * Function CreateLCLDDecoder() + * + * + *------------------------------------------------------------------------------------------*/ + +ivas_error CreateLCLDDecoder( + LCLDDecoder **psLCLDDecoder_out, + const Word32 iSampleRate, + const Word32 iChannels, + const Word32 iNumBlocks, + const Word32 iRealOnlyOut ) +{ + Word32 n; + Word32 read_length; + ivas_error error; + LCLDDecoder *psLCLDDecoder = NULL; + + assert( iSampleRate == 48000 ); + assert( iNumBlocks == 16 || iNumBlocks == 8 || iNumBlocks == 4 ); + IF( ( psLCLDDecoder = (LCLDDecoder *) malloc( sizeof( LCLDDecoder ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + psLCLDDecoder->iSampleRate = iSampleRate; + move32(); + psLCLDDecoder->iChannels = iChannels; + psLCLDDecoder->iAllocOffset = 0; + psLCLDDecoder->iRealOnlyOut = iRealOnlyOut; + if ( iRealOnlyOut == 1 ) + { + psLCLDDecoder->iNumBlocks = L_shr( iNumBlocks, 1 ); + } + else + { + psLCLDDecoder->iNumBlocks = iNumBlocks; + } + psLCLDDecoder->iNumBands = 0; /* read from bitstream*/ + move32(); + psLCLDDecoder->piBandwidths = c_aiBandwidths48; + + psLCLDDecoder->iMSMode = 0; + move32(); + IF( ( psLCLDDecoder->piMSFlags = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + FOR( n = 0; n < MAX_BANDS; n++ ) + { + psLCLDDecoder->piLRPhaseDiffs[n] = 0; + move32(); + psLCLDDecoder->piMSPredCoefs[n] = 0; + move32(); + } + + psLCLDDecoder->iCommonGrouping = 1; /* Common grouping always on only impacts stereo */ + move32(); + IF( ( psLCLDDecoder->piNumGroups = (Word32 *) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->ppiGroupLengths = (Word32 **) malloc( psLCLDDecoder->iChannels * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiRMSEnvelope = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiSMR = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiExcitation = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiAlloc = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDDecoder->pppiLCLDSignReal = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiLCLDSignImag = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiQLCLDReal = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiQLCLDImag = (Word32 ***) malloc( psLCLDDecoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + FOR( n = 0; n < iChannels; n++ ) + { + Word16 k; + IF( ( psLCLDDecoder->ppiGroupLengths[n] = (Word32 *) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiRMSEnvelope[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiSMR[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiExcitation[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiAlloc[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDDecoder->pppiLCLDSignReal[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiLCLDSignImag[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiQLCLDReal[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiQLCLDImag[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + IF( ( psLCLDDecoder->pppiRMSEnvelope[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiSMR[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiExcitation[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiAlloc[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDDecoder->pppiLCLDSignReal[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiLCLDSignImag[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiQLCLDReal[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( psLCLDDecoder->pppiQLCLDImag[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + } + } + + read_length = READ_LENGTH; + move32(); + FOR( n = 0; n < shl( ALLOC_TABLE_SIZE, 1 ); n++ ) + { + psLCLDDecoder->num_decode_table[n] = 1; + move32(); + IF( c_apauiHuffEncTabels[n] != NULL ) + { + CreateDecodeTable( psLCLDDecoder, n, c_apauiHuffEncTabels[n], num_row_aauiLCLDHuff[n], read_length, &psLCLDDecoder->num_decode_table[n] ); + } + ELSE + { + psLCLDDecoder->c_apauiHuffDecTable_RAM[n] = NULL; + } + } + + IF( ( error = CreatePredictionDecoder_fx( &psLCLDDecoder->psPredictionDecoder, iChannels, psLCLDDecoder->iNumBlocks ) ) != IVAS_ERR_OK ) + { + return error; + } + psLCLDDecoder->psNoiseGen = NULL; /* CreateNoiseGen(); No noise fill for now*/ + *psLCLDDecoder_out = psLCLDDecoder; + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------------------------* + * Function DeleteLCLDDecoder() + * + * + *------------------------------------------------------------------------------------------*/ + +void DeleteLCLDDecoder( LCLDDecoder *psLCLDDecoder ) +{ + Word32 k, n; + + IF( psLCLDDecoder != NULL ) + { + IF( psLCLDDecoder->piMSFlags != NULL ) + { + free( psLCLDDecoder->piMSFlags ); + } + + IF( psLCLDDecoder->piNumGroups != NULL ) + { + free( psLCLDDecoder->piNumGroups ); + } + + IF( psLCLDDecoder->ppiGroupLengths != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + free( psLCLDDecoder->ppiGroupLengths[n] ); + } + free( psLCLDDecoder->ppiGroupLengths ); + } + + IF( psLCLDDecoder->pppiRMSEnvelope != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiRMSEnvelope[n][k] ); + } + free( psLCLDDecoder->pppiRMSEnvelope[n] ); + } + free( psLCLDDecoder->pppiRMSEnvelope ); + } + + IF( psLCLDDecoder->pppiSMR != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiSMR[n][k] ); + } + free( psLCLDDecoder->pppiSMR[n] ); + } + free( psLCLDDecoder->pppiSMR ); + } + + IF( psLCLDDecoder->pppiExcitation != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiExcitation[n][k] ); + } + free( psLCLDDecoder->pppiExcitation[n] ); + } + free( psLCLDDecoder->pppiExcitation ); + } + + + IF( psLCLDDecoder->pppiAlloc != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiAlloc[n][k] ); + } + free( psLCLDDecoder->pppiAlloc[n] ); + } + free( psLCLDDecoder->pppiAlloc ); + } + + IF( psLCLDDecoder->pppiLCLDSignReal != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiLCLDSignReal[n][k] ); + } + free( psLCLDDecoder->pppiLCLDSignReal[n] ); + } + free( psLCLDDecoder->pppiLCLDSignReal ); + } + + IF( psLCLDDecoder->pppiLCLDSignImag != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiLCLDSignImag[n][k] ); + } + free( psLCLDDecoder->pppiLCLDSignImag[n] ); + } + free( psLCLDDecoder->pppiLCLDSignImag ); + } + + IF( psLCLDDecoder->pppiQLCLDReal != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiQLCLDReal[n][k] ); + } + free( psLCLDDecoder->pppiQLCLDReal[n] ); + } + free( psLCLDDecoder->pppiQLCLDReal ); + } + + IF( psLCLDDecoder->pppiQLCLDImag != NULL ) + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDDecoder->pppiQLCLDImag[n][k] ); + } + free( psLCLDDecoder->pppiQLCLDImag[n] ); + } + free( psLCLDDecoder->pppiQLCLDImag ); + } + + FOR( n = 0; n < ALLOC_TABLE_SIZE * 2; n++ ) + { + IF( psLCLDDecoder->num_decode_table[n] > 1 ) + { + + IF( psLCLDDecoder->c_apauiHuffDecTable_RAM[n] != NULL ) + { + free( psLCLDDecoder->c_apauiHuffDecTable_RAM[n] ); + } + } + } + + IF( psLCLDDecoder->psPredictionDecoder != NULL ) + { + DeletePredictionDecoder_fx( psLCLDDecoder->psPredictionDecoder ); + psLCLDDecoder->psPredictionDecoder = NULL; + } + + IF( psLCLDDecoder->psNoiseGen != NULL ) + { + DeleteNoiseGen( psLCLDDecoder->psNoiseGen ); + } + + free( psLCLDDecoder ); + } +} + +/*------------------------------------------------------------------------------------------* + * Local function declarations + * + * + *------------------------------------------------------------------------------------------*/ + +static void ApplyRMSEnvelope_fx( const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iNumGroups, const int32_t *piGroupLengths, int32_t **ppiRMSEnvelope, Word32 **ppfReal_fx, Word32 **ppfImag_fx ); +static void ReplaceSign_fx( const Word32 iNumBlocks, const Word32 iNumLCLDBands, Word32 **ppiSignReal, Word32 **ppiSignImag, Word32 **ppfReal, Word32 **ppfImag, const Word32 *piBandwidths ); + +static void InvQuantizeSpectrum_fx( const Word32 iNumGroups, const Word32 *piGroupLengths, const Word32 iNumBands, const Word32 *piBandwidths, Word32 **ppiAlloc, Word32 **ppiQReal, Word32 **ppiQImag, Word32 **ppfReal, Word32 **ppfImag, NoiseGen *psNoiseGen ); +static void InvMSCoding_fx( const Word32 iNumBlocks, const Word32 iNumBands, const Word32 *piBandwidths, const Word32 iMSMode, const Word32 *piMSFlags, const Word32 *piLRPhaseDiffs, const Word32 *piMSPredCoefs, Word32 ***pppfReal, Word32 ***pppfImag ); +// static void InvMSCoding_fx( const int32_t iNumBlocks, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t iMSMode, const int32_t *piMSFlags, const int32_t *piLRPhaseDiffs, const int32_t *piMSPredCoefs, float ***pppfReal, float ***pppfImag, Word32 ***pppfReal_fx, Word32 ***pppfImag_fx,Word16 exp ); + +static Word32 ReadHeaderInformation( Word32 *piNumBands, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 ReadMSInformation( const Word32 iNumBands, Word32 *piMSMode, Word32 *piMSFlags, Word32 *piLRPhaseDiffs, Word32 *piMSPredCoefs, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 ReadGroupInformation( const Word32 iChannels, const Word32 iNumBlocks, Word32 *piCommonGrouping, Word32 *piNumGroups, Word32 **ppiGroupLengths, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 ReadHuff( const UWord32 ( *pauiHuffDecTable )[HUFF_DEC_TABLE_SIZE], Word32 *piSymbol, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 ReadRMSEnvelope( const Word32 iChannels, const Word32 *piNumGroups, const Word32 iNumBands, Word32 ***pppiRMSEnvelope, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 ReadAllocInformation( Word32 *piAllocOffset, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +// static int32_t +// ReadLCLDData( const int32_t iNumGroups, const int32_t *piGroupLengths, const int32_t iNumBands, const int32_t *piBandwidths, const int32_t *piPredEnable, int32_t **ppiAlloc, int32_t **ppiSignReal, int32_t **ppiSignImag, int32_t **ppiQReal, int32_t **ppiQImag, ISAR_SPLIT_REND_BITS_HANDLE pBits, uint32_t ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] ); +static Word32 ReadLCLDData_fx( const Word32 *piNumGroups, Word32 **ppiGroupLengths, const Word32 iNumBands, const Word32 iNumChannels, Word32 **ppiDecodingUnresolved, Word32 **ppiPredEnable, const Word32 iNumSubSets, const Word32 iSubSetId, Word32 ***pppiAlloc, Word32 ***pppiSignReal, Word32 ***pppiSignImag, Word32 ***pppiQReal, Word32 ***pppiQImag, Word32 **ppiDecodingFailed, ISAR_SPLIT_REND_BITS_HANDLE pBits, UWord32 ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] ); +static void ComputeAllocation( const Word32 iChannels, const Word32 *piNumGroups, const Word32 iNumBands, Word32 ***pppiSMR, const Word32 iAllocOffset, Word32 ***pppiAlloc ); + +void SetDecodingUnresolved( LCLDDecoder *psLCLDDecoder ) +{ + int32_t n, ch; + PredictionDecoder *psPredictionDecoder = psLCLDDecoder->psPredictionDecoder; + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + psPredictionDecoder->ppiDecodingUnresolved[ch][n] = 1; + psPredictionDecoder->ppiDecodingFailed[ch][n] = 1; + psPredictionDecoder->ppiDecodingFailedPrev[ch][n] = 1; + } + } +} + +int32_t AnyDecodingFailedPrev( LCLDDecoder *psLCLDDecoder ) +{ + int32_t n, ch; + PredictionDecoder *psPredictionDecoder = psLCLDDecoder->psPredictionDecoder; + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + if ( psPredictionDecoder->ppiDecodingFailedPrev[ch][n] == 1 ) + { + return 1; + } + } + } + return 0; +} + +int32_t AnyDecodingFailed( LCLDDecoder *psLCLDDecoder ) +{ + int32_t n, ch; + PredictionDecoder *psPredictionDecoder = psLCLDDecoder->psPredictionDecoder; + for ( ch = 0; ch < psPredictionDecoder->iChannels; ch++ ) + { + for ( n = 0; n < psPredictionDecoder->iNumSubSets; n++ ) + { + if ( psPredictionDecoder->ppiDecodingFailed[ch][n] == 1 ) + { + return 1; + } + } + } + return 0; +} + +int32_t **GetDecodingFailedStatus( LCLDDecoder *psLCLDDecoder ) +{ + return psLCLDDecoder->psPredictionDecoder->ppiDecodingFailed; +} + +int16_t GetNumSubSets( LCLDDecoder *psLCLDDecoder ) +{ + return (int16_t) psLCLDDecoder->psPredictionDecoder->iNumSubSets; +} + +int32_t **GetDecodingFailedPrevStatus( LCLDDecoder *psLCLDDecoder ) +{ + return psLCLDDecoder->psPredictionDecoder->ppiDecodingFailedPrev; +} + +static void UnpackReal_fx( + const Word32 iChannels, + const Word32 iNumBlocks, + Word32 ***pppfReal_fx, + Word32 ***pppfImag_fx ) +{ + Word32 ch, b, n; + FOR( ch = 0; ch < iChannels; ch++ ) + { + FOR( b = 0; b < LCLD_BANDS; b++ ) + { + Word32 iRealBlock = iNumBlocks - 1; + FOR( n = iNumBlocks / 2 - 1; n >= 0; n-- ) + { + pppfReal_fx[ch][iRealBlock][b] = L_shl( pppfImag_fx[ch][n][b], 1 ); + pppfReal_fx[ch][iRealBlock - 1][b] = L_shl( pppfReal_fx[ch][n][b], 1 ); + pppfImag_fx[ch][iRealBlock][b] = 0; + pppfImag_fx[ch][iRealBlock - 1][b] = 0; + iRealBlock -= 2; + } + } + } +} +/*------------------------------------------------------------------------------------------* + * Function DecodeLCLDFrame() + * + * + *------------------------------------------------------------------------------------------*/ + +Word32 DecodeLCLDFrame( + LCLDDecoder *psLCLDDecoder, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word32 ***pppfLCLDReal_fx, + Word32 ***pppfLCLDImag_fx, + Word16 Q_in, + Word16 *Q_out ) +{ + Word32 k, n; + // FILE *ptr = fopen( "cldfb_real.txt", "ab+" ); + // FILE *ptr1 = fopen( "cldfb_imag.txt", "ab+" ); + ReadHeaderInformation( &psLCLDDecoder->iNumBands, pBits ); + + IF( EQ_32( psLCLDDecoder->iChannels, 2 ) ) + { + ReadMSInformation( psLCLDDecoder->iNumBands, &psLCLDDecoder->iMSMode, psLCLDDecoder->piMSFlags, psLCLDDecoder->piLRPhaseDiffs, psLCLDDecoder->piMSPredCoefs, pBits ); + } + + Word16 i, j; + + ReadPredictors_fx( psLCLDDecoder->psPredictionDecoder, pBits ); + + UpdateDecodingUnresolved( psLCLDDecoder->psPredictionDecoder ); + UpdateDecodingFailedStatus( psLCLDDecoder->psPredictionDecoder ); + + ReadGroupInformation( psLCLDDecoder->iChannels, psLCLDDecoder->iNumBlocks, &psLCLDDecoder->iCommonGrouping, psLCLDDecoder->piNumGroups, psLCLDDecoder->ppiGroupLengths, pBits ); + + ReadRMSEnvelope( psLCLDDecoder->iChannels, (const Word32 *) psLCLDDecoder->piNumGroups, psLCLDDecoder->iNumBands, psLCLDDecoder->pppiRMSEnvelope, pBits ); + + + ReadAllocInformation( &psLCLDDecoder->iAllocOffset, pBits ); + + IF( EQ_32( psLCLDDecoder->iChannels, 2 ) && EQ_32( psLCLDDecoder->iCommonGrouping, 1 ) ) + { /* MS Mode? */ + FOR( k = 0; k < psLCLDDecoder->piNumGroups[0]; k++ ) + { + PerceptualModelStereo_fx( psLCLDDecoder->iNumBands, psLCLDDecoder->piMSFlags, + psLCLDDecoder->pppiRMSEnvelope[0][k], + psLCLDDecoder->pppiRMSEnvelope[1][k], + psLCLDDecoder->pppiExcitation[0][k], + psLCLDDecoder->pppiExcitation[1][k], + psLCLDDecoder->pppiSMR[0][k], + psLCLDDecoder->pppiSMR[1][k] ); + } + } + ELSE + { + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { /* This will be updated to support multiple sample rates*/ + FOR( k = 0; k < psLCLDDecoder->piNumGroups[n]; k++ ) + { + PerceptualModel_fx( (Word16) psLCLDDecoder->iNumBands, psLCLDDecoder->pppiRMSEnvelope[n][k], psLCLDDecoder->pppiExcitation[n][k], psLCLDDecoder->pppiSMR[n][k] ); + } + } + } + + ComputeAllocation( psLCLDDecoder->iChannels, (const Word32 *) psLCLDDecoder->piNumGroups, psLCLDDecoder->iNumBands, psLCLDDecoder->pppiSMR, psLCLDDecoder->iAllocOffset, psLCLDDecoder->pppiAlloc ); + + ReadLCLDData_fx( + psLCLDDecoder->piNumGroups, + psLCLDDecoder->ppiGroupLengths, + psLCLDDecoder->iNumBands, + psLCLDDecoder->iChannels, + psLCLDDecoder->psPredictionDecoder->ppiDecodingUnresolved, + psLCLDDecoder->psPredictionDecoder->ppiPredBandEnable, + psLCLDDecoder->psPredictionDecoder->iNumSubSets, + psLCLDDecoder->psPredictionDecoder->iSubSetId, + psLCLDDecoder->pppiAlloc, + psLCLDDecoder->pppiLCLDSignReal, + psLCLDDecoder->pppiLCLDSignImag, + psLCLDDecoder->pppiQLCLDReal, + psLCLDDecoder->pppiQLCLDImag, + psLCLDDecoder->psPredictionDecoder->ppiDecodingFailed, + pBits, + psLCLDDecoder->c_apauiHuffDecTable_RAM ); + Word16 q_LCLD = Q_in; + + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + InvQuantizeSpectrum_fx( psLCLDDecoder->piNumGroups[n], + (const Word32 *) psLCLDDecoder->ppiGroupLengths[n], + psLCLDDecoder->iNumBands, psLCLDDecoder->piBandwidths, + psLCLDDecoder->pppiAlloc[n], + psLCLDDecoder->pppiQLCLDReal[n], + psLCLDDecoder->pppiQLCLDImag[n], + pppfLCLDReal_fx[n], pppfLCLDImag_fx[n], + psLCLDDecoder->psNoiseGen ); + + ReplaceSign_fx( psLCLDDecoder->iNumBlocks, psLCLDDecoder->iNumBands, + psLCLDDecoder->pppiLCLDSignReal[n], + psLCLDDecoder->pppiLCLDSignImag[n], + pppfLCLDReal_fx[n], pppfLCLDImag_fx[n], psLCLDDecoder->piBandwidths ); + } +#ifdef DEBUG_WRITE_PREDICTORS + { + static FILE *fid; + if ( !fid ) + fid = fopen( "pred_dec.txt", "wt" ); + for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + int16_t b; + for ( b = 0; b < 60; b++ ) + fprintf( fid, "%.5f ", (float) psLCLDDecoder->psPredictionDecoder->ppiPredBandEnable[n][b] * psLCLDDecoder->psPredictionDecoder->ppfA1Imag[n][b] ); + } + fprintf( fid, "%d %d\n", psLCLDDecoder->psPredictionDecoder->iSubSetId, psLCLDDecoder->psPredictionDecoder->piPredChanEnable[n] ); + } +#endif + + ApplyInversePredictors_fx( psLCLDDecoder->psPredictionDecoder, pppfLCLDReal_fx, pppfLCLDImag_fx ); + +#ifdef DEBUG_WRITE + FOR( n = 0; n < psLCLDDecoder->psPredictionDecoder->iChannels; ++n ) + { + FOR( Word16 i = 0; i < psLCLDDecoder->iNumBlocks; i++ ) + { + dbgwrite_txt( pppfLCLDReal[n][i], LCLD_BANDS, "LCLD_real_ApplyInversePredictors_fix.txt", NULL ); + dbgwrite_txt( pppfLCLDImag[n][i], LCLD_BANDS, "LCLD_imag_ApplyInversePredictors_fix.txt", NULL ); + } + } + + FOR( i = 0; i < psLCLDDecoder->psPredictionDecoder->iChannels; ++i ) + { + dbgwrite_txt( psLCLDDecoder->psPredictionDecoder->ppfPredStateReal[i], LCLD_BANDS, "LCLD_Pred_stat_real_ApplyInversePredictors_fix.txt", NULL ); + dbgwrite_txt( psLCLDDecoder->psPredictionDecoder->ppfPredStateImag[i], LCLD_BANDS, "LCLD_Pred_stat_imag_ApplyInversePredictors_fix.txt", NULL ); + } + +#endif + + Word16 Q = 7; + *Q_out = Q; + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ ) + { + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + pppfLCLDReal_fx[n][i][j] = L_shl( pppfLCLDReal_fx[n][i][j], Q - q_LCLD ); + pppfLCLDImag_fx[n][i][j] = L_shl( pppfLCLDImag_fx[n][i][j], Q - q_LCLD ); + } + } + ApplyRMSEnvelope_fx( psLCLDDecoder->iNumBands, psLCLDDecoder->piBandwidths, + psLCLDDecoder->piNumGroups[n], + (const Word32 *) psLCLDDecoder->ppiGroupLengths[n], + psLCLDDecoder->pppiRMSEnvelope[n], + pppfLCLDReal_fx[n], pppfLCLDImag_fx[n] ); + } + + IF( EQ_32( psLCLDDecoder->iChannels, 2 ) && GT_32( psLCLDDecoder->iMSMode, 0 ) ) + { + Word16 exp1 = Q31 - *Q_out; + Word16 exp2 = Q31 - *Q_out; + Word32 real_max = 0; + Word32 imag_max = 0; + Word16 exp; + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( i = 0; i < psLCLDDecoder->iNumBlocks; i++ ) + { + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + real_max = L_max( real_max, L_abs( pppfLCLDReal_fx[n][i][j] ) ); + imag_max = L_max( imag_max, L_abs( pppfLCLDImag_fx[n][i][j] ) ); + } + } + } + IF( NE_32( real_max, 0 ) ) + { + exp1 = s_min( exp1, norm_l( real_max ) ); + } + IF( NE_32( imag_max, 0 ) ) + { + exp2 = s_min( exp2, norm_l( imag_max ) ); + } + IF( NE_32( real_max, 0 ) || NE_32( imag_max, 0 ) ) + { + exp = min( exp2, exp1 ); + *Q_out = add( *Q_out, sub( exp, 3 ) ); + FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + FOR( i = 0; i < psLCLDDecoder->iNumBlocks; i++ ) + { + FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + pppfLCLDReal_fx[n][i][j] = L_shl( pppfLCLDReal_fx[n][i][j], exp - 3 ); + pppfLCLDImag_fx[n][i][j] = L_shl( pppfLCLDImag_fx[n][i][j], exp - 3 ); + } + } + } + } + InvMSCoding_fx( psLCLDDecoder->iNumBlocks, psLCLDDecoder->iNumBands, + psLCLDDecoder->piBandwidths, psLCLDDecoder->iMSMode, + (const Word32 *) psLCLDDecoder->piMSFlags, + (const Word32 *) psLCLDDecoder->piLRPhaseDiffs, + (const Word32 *) psLCLDDecoder->piMSPredCoefs, + pppfLCLDReal_fx, pppfLCLDImag_fx ); + +#ifdef DEBUG_WRITE + for ( n = 0; n < psLCLDDecoder->iChannels; n++ ) + { + Word32 pppfLCLDReal_dbg[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 pppfLCLDImag_dbg[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + for ( i = 0; i < psLCLDDecoder->iNumBlocks; i++ ) + { + for ( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + pppfLCLDReal_dbg[n][i][j] = (float) pppfLCLDReal_fx[n][i][j] / ( 1 << ( exp - 3 ) ); + pppfLCLDImag_dbg[n][i][j] = (float) pppfLCLDImag_fx[n][i][j] / ( 1 << ( exp - 3 ) ); + } + } + { + for ( Word16 i = 0; i < psLCLDDecoder->iNumBlocks; i++ ) + { + dbgwrite_txt( pppfLCLDReal_dbg[n][i], CLDFB_NO_CHANNELS_MAX, "LCLD_real_Inv_MS.txt", NULL ); + dbgwrite_txt( pppfLCLDImag_dbg[n][i], CLDFB_NO_CHANNELS_MAX, "LCLD_imag_Inv_MS.txt", NULL ); + } + } + } +#endif + } + IF( EQ_32( psLCLDDecoder->iRealOnlyOut, 1 ) ) + { + UnpackReal_fx( psLCLDDecoder->iChannels, + psLCLDDecoder->iNumBlocks * 2, + pppfLCLDReal_fx, + pppfLCLDImag_fx ); + } + + return AnyDecodingUnresolved( psLCLDDecoder->psPredictionDecoder ); +} +/*------------------------------------------------------------------------------------------* + * Local functions + * + * + *------------------------------------------------------------------------------------------*/ +static void ApplyRMSEnvelope_fx( + const Word32 iNumBands, + const Word32 *piBandwidths, + const Word32 iNumGroups, + const Word32 *piGroupLengths, + Word32 **ppiRMSEnvelope, + Word32 **ppfReal_fx, + Word32 **ppfImag_fx ) +{ + Word32 b, k, n; + +#ifdef DEBUG + FILE *fp_real, *fp_imag, *fp_real_fx, *fp_imag_fx, *fp_real_inp, *fp_imag_inp, *fp_real_inp_fx, *fp_imag_inp_fx; + fp_real = fopen( "Float_code_real1.txt", "ab+" ); + fp_imag = fopen( "Float_code_imag1.txt", "ab+" ); + fp_real_fx = fopen( "Fixed_code_real1.txt", "ab+" ); + fp_imag_fx = fopen( "Fixed_code_imag1.txt", "ab+" ); + fp_real_inp = fopen( "real_input.txt", "ab+" ); + fp_imag_inp = fopen( "imag_input.txt", "ab+" ); +#endif + + Word32 iBlockOffset, iFBOffset; + + iBlockOffset = 0; + FOR( n = 0; n < iNumGroups; n++ ) + { + FOR( k = 0; k < piGroupLengths[n]; k++ ) + { + iFBOffset = 0; + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 m; + Word32 iRMSEnv; + Word32 fGain_fx; + Word16 fGain_exp; + + iRMSEnv = ppiRMSEnvelope[n][b]; + IF( ( ENV_RECONSTRUCT_TABLE_CENTER + iRMSEnv ) % 2 == 0 ) + { + fGain_fx = 1073741824; // 2 ^ 30 + } + ELSE + { + fGain_fx = 1518500249; // sqrt(2) * 2 ^ 30 + } + fGain_exp = c_afRMSEnvReconstructTable_exp[ENV_RECONSTRUCT_TABLE_CENTER + iRMSEnv]; + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + Word64 tmp; +#ifdef DEBUG + fprintf( fp_real_inp, "%.6f\n", ppfReal[iBlockOffset][iFBOffset] ); + fprintf( fp_imag_inp, "%.6f\n", ppfImag[iBlockOffset][iFBOffset] ); +#endif + +#ifdef DEBUG + fprintf( fp_real, "%.6f\n", ppfReal[iBlockOffset][iFBOffset] ); + fprintf( fp_imag, "%.6f\n", ppfImag[iBlockOffset][iFBOffset] ); +#endif + tmp = W_mult_32_32( fGain_fx, ppfReal_fx[iBlockOffset][iFBOffset] ); + tmp = W_shr( tmp, fGain_exp + 1 ); + ppfReal_fx[iBlockOffset][iFBOffset] = W_extract_l( tmp ); + + tmp = W_mult_32_32( fGain_fx, ppfImag_fx[iBlockOffset][iFBOffset] ); + tmp = W_shr( tmp, fGain_exp + 1 ); + ppfImag_fx[iBlockOffset][iFBOffset] = W_extract_l( tmp ); + +#ifdef DEBUG + fprintf( fp_real_fx, "%.6f\n", (float) ppfReal_fx[iBlockOffset][iFBOffset] / ( 1 << Q ) ); + fprintf( fp_imag_fx, "%.6f\n", (float) ppfImag_fx[iBlockOffset][iFBOffset] / ( 1 << Q ) ); +#endif + + iFBOffset++; + } + } + iBlockOffset++; + } + } +#ifdef DEBUG + fclose( fp_real ); + fclose( fp_imag ); + fclose( fp_imag_fx ); + fclose( fp_real_fx ); + fclose( fp_real_inp ); + fclose( fp_imag_inp ); +#endif + + return; +} + +static void ReplaceSign_fx( + const Word32 iNumBlocks, + const Word32 iNumLCLDBands, + Word32 **ppiSignReal, + Word32 **ppiSignImag, + Word32 **ppfReal, + Word32 **ppfImag, + const Word32 *piBandwidths ) +{ + Word32 b, n; + Word32 m, idx; + + FOR( n = 0; n < iNumBlocks; n++ ) + { + idx = 0; + move32(); + FOR( b = 0; b < iNumLCLDBands; b++ ) + { + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + IF( EQ_32( ppiSignReal[n][idx], 1 ) ) + { + ppfReal[n][idx] = L_negate( ppfReal[n][idx] ); + move32(); + } + + IF( EQ_32( ppiSignImag[n][idx], 1 ) ) + { + ppfImag[n][idx] = L_negate( ppfImag[n][idx] ); + move32(); + } + idx++; + } + } + } + return; +} + +static void InvQuantizeSpectrum_fx( + const Word32 iNumGroups, + const Word32 *piGroupLengths, + const Word32 iNumBands, + const Word32 *piBandwidths, + Word32 **ppiAlloc, + Word32 **ppiQReal, + Word32 **ppiQImag, + Word32 **ppfReal, + Word32 **ppfImag, + NoiseGen *psNoiseGen /* Pass in NULL to switch off noise gen */ +) +{ + Word32 b, k, n; + Word32 iBlockOffest, iFBOffset; + + iBlockOffest = 0; + move32(); + FOR( n = 0; n < iNumGroups; n++ ) + { + FOR( k = 0; k < piGroupLengths[n]; k++ ) + { + iFBOffset = 0; + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 m; + Word32 iAlloc; + Word32 fInvSCFGain; + + iAlloc = ppiAlloc[n][b]; + move32(); + fInvSCFGain = c_afInvScaleFactor_fx[iAlloc]; // Q29 + move32(); + IF( GT_32( iAlloc, 0 ) ) + { + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + Word16 iQuantValue; + + iQuantValue = (Word16) ppiQReal[iBlockOffest][iFBOffset]; + move16(); + ppfReal[iBlockOffest][iFBOffset] = Mpy_32_16_1( fInvSCFGain, iQuantValue ); // Q14 + move32(); + iQuantValue = (Word16) ppiQImag[iBlockOffest][iFBOffset]; + move16(); + ppfImag[iBlockOffest][iFBOffset] = Mpy_32_16_1( fInvSCFGain, iQuantValue ); // Q14 + move32(); + iFBOffset++; + } + } + ELSE IF( psNoiseGen != NULL ) + { + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + ppfReal[iBlockOffest][iFBOffset] = Mpy_32_16_1( GetNoise_fx( psNoiseGen ), 22938 ); // Q(14 + 15 -15 )=Q14 + move32(); + ppfImag[iBlockOffest][iFBOffset] = Mpy_32_16_1( GetNoise_fx( psNoiseGen ), 22938 ); // Q(14+ 15 -15 )=Q14 + move32(); + iFBOffset++; + } + } + ELSE + { + iFBOffset = L_add( iFBOffset, piBandwidths[b] ); + move32(); + } + } + + iBlockOffest++; + } + } + + return; +} + +static void InvMSCoding_fx( + const Word32 iNumBlocks, + const Word32 iNumBands, + const Word32 *piBandwidths, + const Word32 iMSMode, + const Word32 *piMSFlags, + const Word32 *piLRPhaseDiffs, + const Word32 *piMSPredCoefs, + Word32 ***pppfReal, + Word32 ***pppfImag ) +{ + + IF( GT_32( iMSMode, 0 ) ) + { + Word32 b; + Word32 iFBOffset; + Word32 bMSPred = 0; + move32(); + + iFBOffset = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + IF( EQ_32( piMSFlags[b], 1 ) ) + { + Word32 n; + Word32 phaseIdx; + + Word32 fPred; + + phaseIdx = piLRPhaseDiffs[bMSPred] - PHASE_MIN_VAL; + move32(); + fPred = dequantPred_fx( piMSPredCoefs[bMSPred] ); + move32(); + FOR( n = 0; n < piBandwidths[b]; n++ ) + { + Word32 k; + FOR( k = 0; k < iNumBlocks; k++ ) + { + Word32 fLeftReal; + Word32 fLeftImag; + Word32 fRightReal; + Word32 fRightImag; + + IF( EQ_32( iMSMode, 3 ) ) + { + pppfReal[1][k][iFBOffset] = L_add( pppfReal[1][k][iFBOffset], Mpy_32_32( fPred, pppfReal[0][k][iFBOffset] ) ); + move32(); + pppfImag[1][k][iFBOffset] = L_add( pppfImag[1][k][iFBOffset], Mpy_32_32( fPred, pppfImag[0][k][iFBOffset] ) ); + move32(); + } + + fLeftReal = L_add( pppfReal[0][k][iFBOffset], pppfReal[1][k][iFBOffset] ); + fLeftImag = L_add( pppfImag[0][k][iFBOffset], pppfImag[1][k][iFBOffset] ); + fRightReal = L_sub( pppfReal[0][k][iFBOffset], pppfReal[1][k][iFBOffset] ); + fRightImag = L_sub( pppfImag[0][k][iFBOffset], pppfImag[1][k][iFBOffset] ); + + IF( EQ_32( iMSMode, 3 ) ) + { + cplxmult_fx( &fRightReal, &fRightImag, c_afRotRealImag_fx[phaseIdx][0], -c_afRotRealImag_fx[phaseIdx][1] ); + } + + pppfReal[0][k][iFBOffset] = fLeftReal; + move32(); + pppfReal[1][k][iFBOffset] = fRightReal; + move32(); + pppfImag[0][k][iFBOffset] = fLeftImag; + move32(); + pppfImag[1][k][iFBOffset] = fRightImag; + move32(); + } + iFBOffset++; + } + bMSPred++; + } + ELSE + { + iFBOffset = L_add( iFBOffset, piBandwidths[b] ); + move32(); + } + } + } + + return; +} + +/* Currently only the number of bands in frame */ +static Word32 ReadHeaderInformation( + Word32 *piNumBands, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsRead; + + iBitsRead = 0; + move32(); + *piNumBands = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 5 ); + iBitsRead = L_add( iBitsRead, 5 ); + + return iBitsRead; +} + + +static Word32 ReadMSInformation( + const Word32 iNumBands, + Word32 *piMSMode, + Word32 *piMSFlags, + Word32 *piLRPhaseDiffs, + Word32 *piMSPredCoefs, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsRead; + + iBitsRead = 0; + move32(); + *piMSMode = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 2 ); + iBitsRead = L_add( iBitsRead, 2 ); + + IF( EQ_32( *piMSMode, 0 ) ) + { + Word32 n; + FOR( n = 0; n < iNumBands; n++ ) + { + piMSFlags[n] = 0; + move32(); + } + } + ELSE IF( EQ_32( *piMSMode, 1 ) ) + { + Word32 n; + FOR( n = 0; n < iNumBands; n++ ) + { + piMSFlags[n] = 1; + move32(); + } + } + ELSE IF( EQ_32( *piMSMode, 2 ) ) + { + Word32 n; + FOR( n = 0; n < iNumBands; n++ ) + { + piMSFlags[n] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + move32(); + iBitsRead = L_add( iBitsRead, 1 ); + } + } + ELSE IF( EQ_32( *piMSMode, 3 ) ) + { + Word32 n; + Word32 iMSPredAll; + Word32 iNumMSPredBands = 0; + Word32 anyNonZero; + move32(); + iMSPredAll = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + iBitsRead = L_add( iBitsRead, 1 ); + IF( iMSPredAll ) + { + iNumMSPredBands = iNumBands; + move32(); + FOR( n = 0; n < iNumBands; n++ ) + { + piMSFlags[n] = 1; + move32(); + } + } + ELSE + { + FOR( n = 0; n < iNumBands; n++ ) + { + piMSFlags[n] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + move32(); + iBitsRead = L_add( iBitsRead, 1 ); + IF( piMSFlags[n] ) + { + iNumMSPredBands++; + } + } + } + anyNonZero = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + IF( anyNonZero ) + { + piLRPhaseDiffs[0] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, PHASE_BAND0_BITS ); + move32(); + piLRPhaseDiffs[0] = L_add( piLRPhaseDiffs[0], PHASE_MIN_VAL ); + move32(); + iBitsRead = L_add( iBitsRead, PHASE_BAND0_BITS ); + FOR( n = 1; n < iNumMSPredBands; n++ ) + { + Word32 tabIdx; + iBitsRead = L_add( iBitsRead, ReadHuff( c_aaiRMSEnvHuffDec, &tabIdx, pBits ) ); + piLRPhaseDiffs[n] = L_add( tabIdx, ENV_DELTA_MIN ); + move32(); + } + DecodePhase( piLRPhaseDiffs, iNumMSPredBands, PHASE_DIFF_DIM ); + } + ELSE + { + FOR( n = 0; n < iNumMSPredBands; n++ ) + { + piLRPhaseDiffs[n] = 0; + move32(); + } + } + anyNonZero = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + IF( anyNonZero ) + { + piMSPredCoefs[0] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, PRED_BAND0_BITS ); + move32(); + piMSPredCoefs[0] = L_add( piMSPredCoefs[0], PRED_MIN_VAL ); + move32(); + iBitsRead = L_add( iBitsRead, PRED_BAND0_BITS ); + FOR( n = 1; n < iNumMSPredBands; n++ ) + { + Word32 tabIdx; + iBitsRead = L_add( iBitsRead, ReadHuff( c_aaiRMSEnvHuffDec, &tabIdx, pBits ) ); + piMSPredCoefs[n] = L_add( tabIdx, ENV_DELTA_MIN ); + move32(); + } + DecodePredCoef( piMSPredCoefs, iNumMSPredBands ); + } + ELSE + { + FOR( n = 0; n < iNumMSPredBands; n++ ) + { + piMSPredCoefs[n] = 0; + move32(); + } + } +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + IF( !fid ) + fid = fopen( "ms_pred_dec.txt", "wt" ); + writeMSPred( piLRPhaseDiffs, piMSPredCoefs, *piMSMode, iNumMSPredBands, iNumBands, fid, piMSFlags ); + } +#endif + } + ELSE + { + printf( "ERROR UNSUPPORTED MS MODE\n" ); + } + + return iBitsRead; +} + +static Word32 ReadGroupInformation( + const Word32 iChannels, + const Word32 iNumBlocks, + Word32 *piCommonGrouping, + Word32 *piNumGroups, + Word32 **ppiGroupLengths, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 c, k, iBitsRead; + + iBitsRead = 0; + move32(); + IF( EQ_32( iChannels, 2 ) ) + { + *piCommonGrouping = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + move32(); + iBitsRead = L_add( iBitsRead, 1 ); + + IF( EQ_32( *piCommonGrouping, 1 ) ) + { + piNumGroups[0] = 0; + move32(); + ppiGroupLengths[0][piNumGroups[0]] = 1; + move32(); + FOR( k = 0; k < L_sub( iNumBlocks, 1 ); k++ ) + { + Word32 iGroupStart; + + iGroupStart = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + iBitsRead = L_add( iBitsRead, 1 ); + + IF( EQ_32( iGroupStart, 1 ) ) + { + piNumGroups[0] = L_add( piNumGroups[0], 1 ); + move32(); + ppiGroupLengths[0][piNumGroups[0]] = 1; + move32(); + } + ELSE + { + ppiGroupLengths[0][piNumGroups[0]] = L_add( ppiGroupLengths[0][piNumGroups[0]], 1 ); + move32(); + } + } + piNumGroups[0] = L_add( piNumGroups[0], 1 ); + move32(); + + piNumGroups[1] = piNumGroups[0]; + move32(); + FOR( k = 0; k < piNumGroups[1]; k++ ) + { + ppiGroupLengths[1][k] = ppiGroupLengths[0][k]; + move32(); + } + } + ELSE + { + FOR( c = 0; c < iChannels; c++ ) + { + piNumGroups[c] = 0; + move32(); + ppiGroupLengths[c][piNumGroups[c]] = 1; + move32(); + FOR( k = 0; k < L_sub( iNumBlocks, 1 ); k++ ) + { + Word32 iGroupStart; + + iGroupStart = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + iBitsRead = L_add( iBitsRead, 1 ); + + IF( EQ_32( iGroupStart, 1 ) ) + { + piNumGroups[c] = L_add( piNumGroups[c], 1 ); + move32(); + ppiGroupLengths[c][piNumGroups[c]] = 1; + move32(); + } + ELSE + { + ppiGroupLengths[c][piNumGroups[c]] = L_add( ppiGroupLengths[c][piNumGroups[c]], 1 ); + move32(); + } + } + piNumGroups[c] = L_add( piNumGroups[c], 1 ); + move32(); + } + } + } + ELSE + { + FOR( c = 0; c < iChannels; c++ ) + { + piNumGroups[c] = 0; + move32(); + ppiGroupLengths[c][piNumGroups[c]] = 1; + move32(); + FOR( k = 0; k < L_sub( iNumBlocks, 1 ); k++ ) + { + Word32 iGroupStart; + + iGroupStart = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + iBitsRead = L_add( iBitsRead, 1 ); + + IF( EQ_32( iGroupStart, 1 ) ) + { + piNumGroups[c] = L_add( piNumGroups[c], 1 ); + move32(); + ppiGroupLengths[c][piNumGroups[c]] = 1; + move32(); + } + ELSE + { + ppiGroupLengths[c][piNumGroups[c]] = L_add( ppiGroupLengths[c][piNumGroups[c]], 1 ); + } + } + piNumGroups[c] = L_add( piNumGroups[c], 1 ); + } + } + + return iBitsRead; +} + +static Word32 BSForceBack( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word32 iValue, + Word32 iBitCount ) +{ + pBits->bits_read = L_sub( pBits->bits_read, iBitCount ); + + return ( L_shr( iValue, (Word16) iBitCount ) ); +} + + +static Word32 ReadHuff( + const UWord32 ( *pauiHuffDecTable )[HUFF_DEC_TABLE_SIZE], + Word32 *piSymbol, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsRead; + Word32 iSymbol; + Word32 iIndex; + Word32 iVal; + + iVal = 0; + move32(); + iIndex = 0; + move32(); + iSymbol = 0xFFFF; + move32(); + iBitsRead = 0; + move32(); + WHILE( iSymbol == 0xFFFF ) + { + iIndex = ISAR_SPLIT_REND_BITStream_read_int32( pBits, HUFF_READ_SIZE ); + iBitsRead = L_add( iBitsRead, HUFF_READ_SIZE ); + + iIndex = pauiHuffDecTable[iVal][iIndex]; + iSymbol = ( L_and( iIndex, 0xFFFF ) ); + + iVal = ( L_shr( iIndex, 16 ) ); + } + + IF( iVal ) + { + BSForceBack( pBits, iIndex, iVal ); + iBitsRead = L_sub( iBitsRead, iVal ); + } + + *piSymbol = iSymbol; + move32(); + + return iBitsRead; +} + + +static Word32 ReadRMSEnvelope( + const Word32 iChannels, + const Word32 *piNumGroups, + const Word32 iNumBands, + Word32 ***pppiRMSEnvelope, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 b, k, n; + Word32 iBitsRead, iLastRMSVal; + + iBitsRead = 0; + move32(); + FOR( n = 0; n < iChannels; n++ ) + { + FOR( k = 0; k < piNumGroups[n]; k++ ) + { + iLastRMSVal = ISAR_SPLIT_REND_BITStream_read_int32( pBits, ENV0_BITS ); + iBitsRead = L_add( iBitsRead, ENV0_BITS ); + + iLastRMSVal = L_add( iLastRMSVal, ENV_MIN ); + pppiRMSEnvelope[n][k][0] = iLastRMSVal; + move32(); + FOR( b = 1; b < iNumBands; b++ ) + { + Word32 iDelta; + + iBitsRead = L_add( iBitsRead, ReadHuff( c_aaiRMSEnvHuffDec, &iDelta, pBits ) ); + + iDelta = L_add( iDelta, ENV_DELTA_MIN ); + iLastRMSVal = L_add( iDelta, iLastRMSVal ); + pppiRMSEnvelope[n][k][b] = iLastRMSVal; + move32(); + } + } + } + + return iBitsRead; +} + + +static Word32 ReadAllocInformation( + Word32 *piAllocOffset, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsRead; + + iBitsRead = 0; + move32(); + *piAllocOffset = ISAR_SPLIT_REND_BITStream_read_int32( pBits, ALLOC_OFFSET_BITS ); + *piAllocOffset = L_add( *piAllocOffset, MIN_ALLOC_OFFSET ); + iBitsRead = L_add( iBitsRead, ALLOC_OFFSET_BITS ); + + return iBitsRead; +} + +static Word32 ReadLCLDData_fx( + const Word32 *piNumGroups, + Word32 **ppiGroupLengths, + const Word32 iNumBands, + const Word32 iNumChannels, + Word32 **ppiDecodingUnresolved, + Word32 **ppiPredEnable, + const Word32 iNumSubSets, + const Word32 iSubSetId, + Word32 ***pppiAlloc, + Word32 ***pppiSignReal, + Word32 ***pppiSignImag, + Word32 ***pppiQReal, + Word32 ***pppiQImag, + Word32 **ppiDecodingFailed, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + UWord32 ( *c_apauiHuffDecTables[2 * ALLOC_TABLE_SIZE] )[HUFF_DEC_TABLE_SIZE] ) +{ + Word32 iBitsRead; + Word32 iDecodingStopped = 0; + Word32 iNumLcldBands = c_aiNumLcldBandsPerBand[iNumBands - 1]; + Word32 s; + Word32 iSet = iSubSetId; + Word16 tmp, tmp_e; + iBitsRead = 0; + for ( s = 0; s < iNumSubSets; s++, iSet-- ) + { + Word32 ch; + + IF( LT_32( iSet, 0 ) ) + { + iSet = L_sub( iNumSubSets, 1 ); + } + + FOR( ch = 0; ch < iNumChannels; ch++ ) + { + Word32 n; + Word32 iBlockOffest; + + IF( EQ_32( ppiDecodingUnresolved[ch][iSet], 1 ) ) + { + iDecodingStopped = 1; + ppiDecodingFailed[ch][iSet] = 1; /* mark as not decoded (is also initialized like that when a frame is lost */ + } + ELSE + { + ppiDecodingFailed[ch][iSet] = 0; /* mark as correctly decoded */ + } + iBlockOffest = 0; + FOR( n = 0; n < piNumGroups[ch]; n++ ) + { + Word32 k; + FOR( k = 0; k < ppiGroupLengths[ch][n]; k++ ) + { + Word32 iFBOffset; + + FOR( iFBOffset = iSet; iFBOffset < iNumLcldBands; iFBOffset += iNumSubSets ) + { + Word32 b; + Word32 iAlloc; + Word32 iHuffDim; + Word32 iHuffMod; + + b = c_aiBandIdPerLcldBand[iFBOffset]; + + iAlloc = pppiAlloc[ch][n][b]; + + iHuffDim = c_aiHuffmanDim_fx[iAlloc]; + iHuffMod = c_aiHuffmanMod_fx[iAlloc]; + + IF( EQ_32( iDecodingStopped, 1 ) ) + { + pppiQReal[ch][iBlockOffest][iFBOffset] = 0; + pppiQImag[ch][iBlockOffest][iFBOffset] = 0; + pppiSignReal[ch][iBlockOffest][iFBOffset] = 0; + pppiSignImag[ch][iBlockOffest][iFBOffset] = 0; + } + ELSE IF( GT_32( iAlloc, 0 ) ) + { + const UWord32( *pauiHuffmanTable )[HUFF_DEC_TABLE_SIZE] = NULL; + const UWord32( *pauiHuffmanTableDPCM )[HUFF_DEC_TABLE_SIZE] = NULL; + Word32 iQuantValue1 = 0; + Word32 iQuantValue2 = 0; +#ifdef USE_DEMOD_TABLES + const int32_t( *paiDemodTable )[2] = NULL; +#endif + pauiHuffmanTable = (const UWord32( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[iAlloc]; + pauiHuffmanTableDPCM = (const UWord32( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[ALLOC_TABLE_SIZE + iAlloc]; +#ifdef USE_DEMOD_TABLES + paiDemodTable = c_apaiDemodTables[iAlloc]; +#endif +#ifdef LCLD_HANDLE_PRED_START_SAMPLE + if ( ppiPredEnable[ch][iFBOffset] == 1 && ( iBlockOffest > 0 || iSet != iSubSetId ) ) +#else + IF( EQ_32( ppiPredEnable[ch][iFBOffset], 1 ) ) +#endif + { + IF( EQ_32( iHuffDim, 2 ) ) + { + Word32 iSymbol; + iBitsRead = L_add( iBitsRead, ReadHuff( pauiHuffmanTableDPCM, &iSymbol, pBits ) ); +#ifdef USE_DEMOD_TABLES + iQuantValue1 = paiDemodTable[iSymbol][0]; + iQuantValue2 = paiDemodTable[iSymbol][1]; +#else + tmp = BASOP_Util_Divide1616_Scale( (Word16) iSymbol, (Word16) iHuffMod, &tmp_e ); + iQuantValue1 = L_deposit_l( shr( tmp, add( 15, negate( tmp_e ) ) ) ); + // iQuantValue1 = iSymbol / iHuffMod; + iQuantValue2 = iSymbol % iHuffMod; +#endif + } + ELSE + { + iBitsRead = L_add( iBitsRead, ReadHuff( pauiHuffmanTableDPCM, &iQuantValue1, pBits ) ); + iBitsRead = L_add( iBitsRead, ReadHuff( pauiHuffmanTableDPCM, &iQuantValue2, pBits ) ); + } + } + ELSE + { + IF( EQ_32( iHuffDim, 2 ) ) + { + Word32 iSymbol; + + iBitsRead = L_add( iBitsRead, ReadHuff( pauiHuffmanTable, &iSymbol, pBits ) ); +#ifdef USE_DEMOD_TABLES + iQuantValue1 = paiDemodTable[iSymbol][0]; + iQuantValue2 = paiDemodTable[iSymbol][1]; +#else + tmp = BASOP_Util_Divide1616_Scale( (Word16) iSymbol, (Word16) iHuffMod, &tmp_e ); + iQuantValue1 = L_deposit_l( shr( tmp, add( 15, negate( tmp_e ) ) ) ); + iQuantValue2 = iSymbol % iHuffMod; +#endif + } + ELSE + { + iBitsRead = L_add( iBitsRead, ReadHuff( pauiHuffmanTable, &iQuantValue1, pBits ) ); + move32(); + iBitsRead = L_add( iBitsRead, ReadHuff( pauiHuffmanTable, &iQuantValue2, pBits ) ); + move32(); + /*iBitsRead += ReadHuff( pauiHuffmanTable, &iQuantValue1, pBits ); + iBitsRead += ReadHuff( pauiHuffmanTable, &iQuantValue2, pBits );*/ + } + } + + pppiQReal[ch][iBlockOffest][iFBOffset] = iQuantValue1; + move32(); + pppiQImag[ch][iBlockOffest][iFBOffset] = iQuantValue2; + move32(); + IF( GT_32( iQuantValue1, 0 ) ) + { + pppiSignReal[ch][iBlockOffest][iFBOffset] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + move32(); + iBitsRead = L_add( iBitsRead, 1 ); + move32(); + } + ELSE + { + pppiSignReal[ch][iBlockOffest][iFBOffset] = 0; + } + IF( GT_32( iQuantValue2, 0 ) ) + { + pppiSignImag[ch][iBlockOffest][iFBOffset] = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + move32(); + iBitsRead = L_add( iBitsRead, 1 ); + move32(); + } + ELSE + { + pppiSignImag[ch][iBlockOffest][iFBOffset] = 0; + } + } + ELSE + { + pppiSignReal[ch][iBlockOffest][iFBOffset] = 0; + move32(); + pppiSignImag[ch][iBlockOffest][iFBOffset] = 0; + move32(); + } + } + iBlockOffest++; + } + } + } + } + + return iBitsRead; +} + +static void ComputeAllocation( + const Word32 iChannels, + const Word32 *piNumGroups, + const Word32 iNumBands, + Word32 ***pppiSMR, + const Word32 iAllocOffset, + Word32 ***pppiAlloc ) +{ + Word32 b, k, n, iAlloc; + + FOR( n = 0; n < iChannels; n++ ) + { + FOR( k = 0; k < piNumGroups[n]; k++ ) + { + FOR( b = 0; b < iNumBands; b++ ) + { + iAlloc = L_shr( L_add( pppiSMR[n][k][b], L_mult0( (Word16) iAllocOffset, ALLOC_OFFSET_SCALE ) ), 5 ); + iAlloc = ( iAlloc > MIN_ALLOC ) ? iAlloc : MIN_ALLOC; + iAlloc = ( iAlloc < MAX_ALLOC ) ? iAlloc : MAX_ALLOC; + pppiAlloc[n][k][b] = iAlloc; + move32(); + } + } + } + + return; +} + +#endif diff --git a/lib_isar/isar_lcld_encoder.c b/lib_isar/isar_lcld_encoder.c new file mode 100644 index 000000000..aa9332c26 --- /dev/null +++ b/lib_isar/isar_lcld_encoder.c @@ -0,0 +1,2143 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include +#include "isar_lcld_prot.h" +#include "isar_lcld_rom_tables.h" +#include "prot.h" +#include "prot_fx2.h" +#include "isar_prot.h" +#include "wmc_auto.h" +#include "basop_util.h" +#include "enh64.h" +#include "basop32.h" +#include "basop_mpy.h" + +#define LOG10_2_FX ( 646456993 ) +/*------------------------------------------------------------------------------------------* + * Local structures + *------------------------------------------------------------------------------------------*/ +struct LCLD_ENCODER +{ + Word32 iSampleRate; + Word32 iChannels; + Word32 iNumBlocks; + + Word32 iTargetBitRate; + + Word32 iNumBands; + const Word32 *piBandwidths; + + Word32 iMSMode; + Word32 *piMSFlags; + Word32 piMSPredCoefs[MAX_BANDS]; + Word32 piLRPhaseDiffs[MAX_BANDS]; + Word32 iAllowSidePred; + + Word32 iRealOnlyOut; + + RMSEnvelopeGrouping *psRMSEnvelopeGrouping; + + Word32 iCommonGrouping; + Word32 *piNumGroups; + Word32 **ppiGroupLengths; + + Word32 ***pppiRMSEnvelope; + Word32 ***pppiSMR; + Word32 ***pppiExcitation; + Word32 ***pppiAlloc; + + Word32 iAllocOffset; + + Word32 ***pppiLCLDSignReal; + Word32 ***pppiLCLDSignImag; + Word32 ***pppiQLCLDReal; + Word32 ***pppiQLCLDImag; + + + PredictionEncoder *psPredictionEncoder; +}; +/*------------------------------------------------------------------------------------------* + * Function Quantize() + * + * + *------------------------------------------------------------------------------------------*/ +static Word32 Quantize_fx( + const Word32 fVal_fx, + const Word32 fScale_fx, + Word32 *iSign, + const Word32 iMaxVal ) +{ + Word32 iVal_fx; + IF( GT_32( fVal_fx, 0 ) ) + { + iVal_fx = (Word32) L_add( Mpy_32_32( fScale_fx, fVal_fx ), ONE_IN_Q20 ); + *iSign = 0; + } + ELSE + { + iVal_fx = (Word32) L_add( Mpy_32_32( -fScale_fx, fVal_fx ), ONE_IN_Q20 ); + *iSign = 1; + } + iVal_fx = ( iVal_fx < iMaxVal ) ? iVal_fx : iMaxVal; + + return iVal_fx; +} +/*------------------------------------------------------------------------------------------* + * Function UnQuantize() + * + * + *------------------------------------------------------------------------------------------*/ +static Word32 UnQuantize_fx( + const Word32 iVal_fx, + const Word32 fScale_fx, + const Word32 iSign ) +{ + + Word32 fVal_fx; + IF( EQ_32( iSign, 0 ) ) + { + fVal_fx = Mpy_32_32( fScale_fx, iVal_fx ); // Q19 + } + ELSE + { + fVal_fx = Mpy_32_32( -fScale_fx, iVal_fx ); // Q19 + } + return fVal_fx; +} +static void PackReal( + const Word32 iChannels, + const Word32 iNumBlocks, + Word32 ***pppfReal, + Word32 ***pppfImag ) +{ + Word32 ch, b, n; + FOR( ch = 0; ch < iChannels; ch++ ) + { + FOR( b = 0; b < LCLD_BANDS; b++ ) + { + Word32 iRealBlock = 0; + move32(); + FOR( n = 0; n < iNumBlocks; n += 2 ) + { + pppfImag[ch][iRealBlock][b] = pppfReal[ch][n + 1][b]; + move32(); + pppfReal[ch][iRealBlock][b] = pppfReal[ch][n][b]; + move32(); + iRealBlock++; + } + } + } +} +/*------------------------------------------------------------------------------------------* + * Function CreateLCLDEncoder() + * + * + *------------------------------------------------------------------------------------------*/ + +ivas_error CreateLCLDEncoder( + LCLDEncoder **psLCLDEncoder_out, + const Word32 iSampleRate, + const Word32 iChannels, + const Word32 iTargetBitRate, + const Word32 iAllowSidePred, + const Word16 iNumBlocks, + const Word16 iNumSubSets, + const Word32 iRealOnlyOut ) +{ + Word32 n; + LCLDEncoder *psLCLDEncoder; + ivas_error error; + Word32 iMaxNumPredBands = 0; + move32(); + + assert( iSampleRate == 48000 ); // Fix + assert( iNumBlocks == 16 || iNumBlocks == 8 || iNumBlocks == 4 ); + assert( iNumSubSets > 0 && iNumSubSets <= LCLD_MAX_NUM_PRED_SUBSETS ); + + IF( ( psLCLDEncoder = (LCLDEncoder *) malloc( sizeof( LCLDEncoder ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + psLCLDEncoder->iSampleRate = iSampleRate; + move32(); + psLCLDEncoder->iChannels = iChannels; + move32(); + psLCLDEncoder->iRealOnlyOut = iRealOnlyOut; + move32(); + psLCLDEncoder->iAllocOffset = 0; + move32(); + + psLCLDEncoder->iTargetBitRate = iTargetBitRate; + move32(); + + psLCLDEncoder->piBandwidths = c_aiBandwidths48; + psLCLDEncoder->iNumBands = DEF_BANDS_48; /* 22 bands = 50 CLDFB bands (rather than 23 bands) */ + move32(); + iMaxNumPredBands = L_min( c_aiNumLcldBandsPerBand[psLCLDEncoder->iNumBands - 1], 50 ); + IF( EQ_32( iRealOnlyOut, 1 ) ) + { + iMaxNumPredBands = 0; + move32(); + assert( iNumSubSets == 1 ); + psLCLDEncoder->iNumBlocks = L_deposit_l( shr( iNumBlocks, 1 ) ); + } + ELSE + { + psLCLDEncoder->iNumBlocks = iNumBlocks; + move32(); + } + + psLCLDEncoder->iMSMode = 0; + move32(); + IF( ( psLCLDEncoder->piMSFlags = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + FOR( n = 0; n < MAX_BANDS; n++ ) + { + psLCLDEncoder->piLRPhaseDiffs[n] = 0; + move32(); + psLCLDEncoder->piMSPredCoefs[n] = 0; + move32(); + } + psLCLDEncoder->iAllowSidePred = iAllowSidePred; + move32(); + + psLCLDEncoder->psRMSEnvelopeGrouping = CreateRMSEnvelopeGrouping( psLCLDEncoder->iNumBlocks ); + + psLCLDEncoder->iCommonGrouping = 1; //*Common grouping always on only impacts stereo */ + move32(); + IF( ( psLCLDEncoder->piNumGroups = (Word32 *) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->ppiGroupLengths = (Word32 **) malloc( psLCLDEncoder->iChannels * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiRMSEnvelope = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiSMR = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiExcitation = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiAlloc = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + + IF( ( psLCLDEncoder->pppiLCLDSignReal = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiLCLDSignImag = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiQLCLDReal = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiQLCLDImag = (Word32 ***) malloc( psLCLDEncoder->iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + + FOR( n = 0; n < iChannels; n++ ) + { + Word32 k; + IF( ( psLCLDEncoder->ppiGroupLengths[n] = (Word32 *) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiRMSEnvelope[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiSMR[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiExcitation[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiAlloc[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + + IF( ( psLCLDEncoder->pppiLCLDSignReal[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiLCLDSignImag[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiQLCLDReal[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiQLCLDImag[n] = (Word32 **) malloc( LCLD_BLOCKS_PER_FRAME * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + IF( ( psLCLDEncoder->pppiRMSEnvelope[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiSMR[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiExcitation[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiAlloc[n][k] = (Word32 *) malloc( MAX_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + + IF( ( psLCLDEncoder->pppiLCLDSignReal[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiLCLDSignImag[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiQLCLDReal[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + IF( ( psLCLDEncoder->pppiQLCLDImag[n][k] = (Word32 *) malloc( LCLD_BANDS * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + } + } + + IF( ( error = CreatePredictionEncoder_fx( &( psLCLDEncoder->psPredictionEncoder ), iChannels, psLCLDEncoder->iNumBlocks, L_deposit_l( iNumSubSets ), iMaxNumPredBands ) ) != IVAS_ERR_OK ) + { + return error; + } + + *psLCLDEncoder_out = psLCLDEncoder; + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------------------------* + * Function DeleteLCLDEncoder() + * + * + *------------------------------------------------------------------------------------------*/ + +void DeleteLCLDEncoder( + LCLDEncoder *psLCLDEncoder ) +{ + Word32 k, n; + + IF( psLCLDEncoder != NULL ) + { + + IF( psLCLDEncoder->piMSFlags != NULL ) + { + free( psLCLDEncoder->piMSFlags ); + } + + IF( psLCLDEncoder->piNumGroups != NULL ) + { + free( psLCLDEncoder->piNumGroups ); + } + + IF( psLCLDEncoder->psRMSEnvelopeGrouping != NULL ) + { + DeleteRMSEnvelopeGrouping( psLCLDEncoder->psRMSEnvelopeGrouping ); + } + + IF( psLCLDEncoder->ppiGroupLengths != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + free( psLCLDEncoder->ppiGroupLengths[n] ); + } + free( psLCLDEncoder->ppiGroupLengths ); + } + IF( psLCLDEncoder->pppiRMSEnvelope != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiRMSEnvelope[n][k] ); + } + free( psLCLDEncoder->pppiRMSEnvelope[n] ); + } + free( psLCLDEncoder->pppiRMSEnvelope ); + } + + IF( psLCLDEncoder->pppiSMR != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiSMR[n][k] ); + } + free( psLCLDEncoder->pppiSMR[n] ); + } + free( psLCLDEncoder->pppiSMR ); + } + + IF( psLCLDEncoder->pppiExcitation != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiExcitation[n][k] ); + } + free( psLCLDEncoder->pppiExcitation[n] ); + } + free( psLCLDEncoder->pppiExcitation ); + } + + IF( psLCLDEncoder->pppiAlloc != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiAlloc[n][k] ); + } + free( psLCLDEncoder->pppiAlloc[n] ); + } + free( psLCLDEncoder->pppiAlloc ); + } + + IF( psLCLDEncoder->pppiLCLDSignReal != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiLCLDSignReal[n][k] ); + } + free( psLCLDEncoder->pppiLCLDSignReal[n] ); + } + free( psLCLDEncoder->pppiLCLDSignReal ); + } + + IF( psLCLDEncoder->pppiLCLDSignImag != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiLCLDSignImag[n][k] ); + } + free( psLCLDEncoder->pppiLCLDSignImag[n] ); + } + free( psLCLDEncoder->pppiLCLDSignImag ); + } + + IF( psLCLDEncoder->pppiQLCLDReal != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiQLCLDReal[n][k] ); + } + free( psLCLDEncoder->pppiQLCLDReal[n] ); + } + free( psLCLDEncoder->pppiQLCLDReal ); + } + + IF( psLCLDEncoder->pppiQLCLDImag != NULL ) + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + FOR( k = 0; k < LCLD_BLOCKS_PER_FRAME; k++ ) + { + free( psLCLDEncoder->pppiQLCLDImag[n][k] ); + } + free( psLCLDEncoder->pppiQLCLDImag[n] ); + } + free( psLCLDEncoder->pppiQLCLDImag ); + } + + DeletePredictionEncoder_fx( psLCLDEncoder->psPredictionEncoder ); + free( psLCLDEncoder ); + } + + return; +} + +/*------------------------------------------------------------------------------------------* + * Local function declarations + *------------------------------------------------------------------------------------------*/ + +static Word32 MSModeCalculation_fx( const Word32 iNumBlocks, const Word32 iNumBands, const Word32 *piBandwidths, Word32 ***pppfReal_fx, Word32 ***pppfImag_fx, Word16 Q_in, Word32 *piMSMode, Word32 *piLRPhaseDiff, Word32 *piMSPredCoef, const Word32 iAllowSidePred, const Word32 iRealOnlyOut, Word32 *piMSFlags ); +static void RemoveRMSEnvelope( const Word32 iNumBands, const Word32 *piBandwidths, const Word32 iNumGroups, const Word32 *piGroupLengths, Word32 **ppiRMSEnvelope, Word32 **ppfReal_fx, Word32 **ppfImag_fx ); +static Word32 CountLCLDBits( const Word32 iNumGroups, const Word32 *piGroupLengths, const Word32 iNumBands, const Word32 *piBandwidths, const Word32 *piPredEnable, Word32 **ppiAlloc, Word32 **ppiQReal, Word32 **ppiQImag ); + +static Word32 WriteHeaderInformation( const Word32 iNumBands, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 WriteMSInformation( const Word32 iNumBands, const Word32 iMSMode, const Word32 *piMSFlags, const Word32 *piLRPhaseDiff, const Word32 *piMSPredCoef, Word32 iNumMSPredBands, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 WriteGroupInformation( const Word32 iChannels, const Word32 iCommonGrouping, const Word32 *piNumGroups, Word32 **ppiGroupLengths, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 WriteRMSEnvelope( const Word32 iChannels, const Word32 *piNumGroups, const Word32 iNumBands, Word32 ***pppiRMSEnvelope, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 WriteAllocInformation( const Word32 iAllocOffset, ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +static Word32 WriteLCLDData( const Word32 *piNumGroups, Word32 **ppiGroupLengths, const Word32 iNumBands, const Word32 iNumChannels, Word32 **ppiPredEnable, const Word32 iNumSubSets, const Word32 iSubSetId, Word32 ***pppiAlloc, Word32 ***pppiSignReal, Word32 ***pppiSignImag, Word32 ***pppiQReal, Word32 ***pppiQImag, ISAR_SPLIT_REND_BITS_HANDLE pBits ); +static Word32 ComputeAllocation( const Word32 iChannels, const Word32 *piNumGroups, Word32 **ppiGroupLengths, const Word32 iNumBands, const Word32 *piBandwidths, Word32 ***pppfReal_fx, Word32 ***pppfImag_fx, Word16 q_final, Word32 ***pppiSMR, const Word32 iAvailableBits, Word32 *piAllocOffset, Word32 ***pppiAlloc, Word32 ***pppiQReal, Word32 ***pppiQImag, Word32 ***pppiSignReal, Word32 ***pppiSignImag, PredictionEncoder *psPredictionEncoder ); +/*------------------------------------------------------------------------------------------* + * Function EncodeLCLDFrame() + * + * + *------------------------------------------------------------------------------------------*/ +Word32 EncodeLCLDFrame( + LCLDEncoder *psLCLDEncoder, + Word32 ***pppfLCLDReal_fx, + Word32 ***pppfLCLDImag_fx, + Word32 *piBitsWritten, + const Word32 available_bits, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word16 *q_final ) +{ + Word32 n; + Word32 iAvailableBits, iBitsWritten; + Word32 iNumMSBands = 0; + Word32 iAudioBitsWritten; + + iAvailableBits = available_bits; // HCBR for now + iBitsWritten = 0; + assert( available_bits <= pBits->buf_len * 8 ); + IF( EQ_32( psLCLDEncoder->iRealOnlyOut, 1 ) ) + { + PackReal( psLCLDEncoder->iChannels, psLCLDEncoder->iNumBlocks * 2, pppfLCLDReal_fx, pppfLCLDImag_fx ); + } + /* Do MS calc here */ + IF( EQ_32( psLCLDEncoder->iChannels, 2 ) ) + { + iNumMSBands = MSModeCalculation_fx( psLCLDEncoder->iNumBlocks, + psLCLDEncoder->iNumBands, + psLCLDEncoder->piBandwidths, + pppfLCLDReal_fx, + pppfLCLDImag_fx, + *q_final, + &psLCLDEncoder->iMSMode, + psLCLDEncoder->piLRPhaseDiffs, + psLCLDEncoder->piMSPredCoefs, + psLCLDEncoder->iAllowSidePred, + psLCLDEncoder->iRealOnlyOut, + psLCLDEncoder->piMSFlags ); + IF( GT_32( psLCLDEncoder->iMSMode, 0 ) ) + { + psLCLDEncoder->iCommonGrouping = 1; // Make sure common grouping is enabled when MS is in use + } + } + /* Compute Grouping and RMS Envelopes */ + IF( EQ_32( psLCLDEncoder->iChannels, 2 ) && EQ_32( psLCLDEncoder->iCommonGrouping, 1 ) ) + { + ComputeEnvelopeGrouping( psLCLDEncoder->psRMSEnvelopeGrouping, + psLCLDEncoder->iChannels, + psLCLDEncoder->iNumBands, + psLCLDEncoder->piBandwidths, + pppfLCLDReal_fx, + pppfLCLDImag_fx, + &psLCLDEncoder->piNumGroups[0], + psLCLDEncoder->ppiGroupLengths[0], + psLCLDEncoder->pppiRMSEnvelope, + *q_final ); + psLCLDEncoder->piNumGroups[1] = psLCLDEncoder->piNumGroups[0]; + FOR( n = 0; n < psLCLDEncoder->piNumGroups[0]; n++ ) + { + psLCLDEncoder->ppiGroupLengths[1][n] = psLCLDEncoder->ppiGroupLengths[0][n]; + move32(); + } + } + ELSE + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + ComputeEnvelopeGrouping( psLCLDEncoder->psRMSEnvelopeGrouping, + psLCLDEncoder->iChannels, + psLCLDEncoder->iNumBands, + psLCLDEncoder->piBandwidths, + &pppfLCLDReal_fx[n], + &pppfLCLDImag_fx[n], + &psLCLDEncoder->piNumGroups[n], + psLCLDEncoder->ppiGroupLengths[n], + &psLCLDEncoder->pppiRMSEnvelope[n], *q_final ); + } + } + + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + RemoveRMSEnvelope( psLCLDEncoder->iNumBands, + psLCLDEncoder->piBandwidths, + psLCLDEncoder->piNumGroups[n], + (const Word32 *) psLCLDEncoder->ppiGroupLengths[n], + psLCLDEncoder->pppiRMSEnvelope[n], + pppfLCLDReal_fx[n], + pppfLCLDImag_fx[n] ); + } + *q_final = add( *q_final, 9 ); // Increasing the Q as it has changed inside the RemoveRMSEnvelope + + ComputePredictors_fx( psLCLDEncoder->psPredictionEncoder, pppfLCLDReal_fx, pppfLCLDImag_fx ); + + iBitsWritten = L_add( iBitsWritten, WriteHeaderInformation( psLCLDEncoder->iNumBands, pBits ) ); + + IF( EQ_32( psLCLDEncoder->iChannels, 2 ) ) + { + iBitsWritten = L_add( iBitsWritten, WriteMSInformation( psLCLDEncoder->iNumBands, + psLCLDEncoder->iMSMode, + (const Word32 *) psLCLDEncoder->piMSFlags, + (const Word32 *) psLCLDEncoder->piLRPhaseDiffs, + (const Word32 *) psLCLDEncoder->piMSPredCoefs, + iNumMSBands, + pBits ) ); + } + + + iBitsWritten = L_add( iBitsWritten, WritePredictors( psLCLDEncoder->psPredictionEncoder, pBits ) ); + + iBitsWritten = L_add( iBitsWritten, WriteGroupInformation( psLCLDEncoder->iChannels, psLCLDEncoder->iCommonGrouping, (const Word32 *) psLCLDEncoder->piNumGroups, psLCLDEncoder->ppiGroupLengths, pBits ) ); + + iBitsWritten = L_add( iBitsWritten, WriteRMSEnvelope( psLCLDEncoder->iChannels, (const Word32 *) psLCLDEncoder->piNumGroups, psLCLDEncoder->iNumBands, psLCLDEncoder->pppiRMSEnvelope, pBits ) ); + + + IF( EQ_32( psLCLDEncoder->iChannels, 2 ) && EQ_32( psLCLDEncoder->iCommonGrouping, 1 ) ) + { + Word32 k; + FOR( k = 0; k < psLCLDEncoder->piNumGroups[0]; k++ ) + { + PerceptualModelStereo_fx( psLCLDEncoder->iNumBands, + psLCLDEncoder->piMSFlags, + psLCLDEncoder->pppiRMSEnvelope[0][k], + psLCLDEncoder->pppiRMSEnvelope[1][k], + psLCLDEncoder->pppiExcitation[0][k], + psLCLDEncoder->pppiExcitation[1][k], + psLCLDEncoder->pppiSMR[0][k], + psLCLDEncoder->pppiSMR[1][k] ); + } + } + ELSE + { + FOR( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + Word32 k; + FOR( k = 0; k < psLCLDEncoder->piNumGroups[n]; k++ ) + { + PerceptualModel_fx( psLCLDEncoder->iNumBands, + psLCLDEncoder->pppiRMSEnvelope[n][k], + psLCLDEncoder->pppiExcitation[n][k], + psLCLDEncoder->pppiSMR[n][k] ); + } + } + } +#ifdef DEBUG_WRITE_PREDICTORS + { + static FILE *fid; + if ( !fid ) + fid = fopen( "pred_enc.txt", "wt" ); + for ( n = 0; n < psLCLDEncoder->iChannels; n++ ) + { + int16_t b; + for ( b = 0; b < 60; b++ ) + fprintf( fid, "%.5f ", (float) psLCLDEncoder->psPredictionEncoder->ppiPredBandEnable[n][b] * psLCLDEncoder->psPredictionEncoder->ppfA1Imag[n][b] ); + } + fprintf( fid, "%d %d\n", psLCLDEncoder->psPredictionEncoder->iSubSetId, psLCLDEncoder->psPredictionEncoder->piPredChanEnable[n] ); + } +#endif + iAvailableBits = L_sub( iAvailableBits, iBitsWritten ); + + ComputeAllocation( psLCLDEncoder->iChannels, + (const Word32 *) psLCLDEncoder->piNumGroups, + psLCLDEncoder->ppiGroupLengths, + psLCLDEncoder->iNumBands, + psLCLDEncoder->piBandwidths, + pppfLCLDReal_fx, + pppfLCLDImag_fx, + *q_final, + psLCLDEncoder->pppiSMR, + iAvailableBits, + &psLCLDEncoder->iAllocOffset, + psLCLDEncoder->pppiAlloc, + psLCLDEncoder->pppiQLCLDReal, + psLCLDEncoder->pppiQLCLDImag, + psLCLDEncoder->pppiLCLDSignReal, + psLCLDEncoder->pppiLCLDSignImag, + psLCLDEncoder->psPredictionEncoder ); + + iBitsWritten = L_add( iBitsWritten, WriteAllocInformation( psLCLDEncoder->iAllocOffset, + pBits ) ); + iAudioBitsWritten = iBitsWritten; + iBitsWritten = L_add( iBitsWritten, WriteLCLDData( psLCLDEncoder->piNumGroups, + psLCLDEncoder->ppiGroupLengths, + psLCLDEncoder->iNumBands, + psLCLDEncoder->iChannels, + psLCLDEncoder->psPredictionEncoder->ppiPredBandEnable, + psLCLDEncoder->psPredictionEncoder->iNumSubSets, + psLCLDEncoder->psPredictionEncoder->iSubSetId, + psLCLDEncoder->pppiAlloc, + psLCLDEncoder->pppiLCLDSignReal, + psLCLDEncoder->pppiLCLDSignImag, + psLCLDEncoder->pppiQLCLDReal, + psLCLDEncoder->pppiQLCLDImag, + pBits ) ); + *piBitsWritten = iBitsWritten; + move32(); + iAudioBitsWritten = L_sub( iBitsWritten, iAudioBitsWritten ); + + UpdatePredictionSubSetId( psLCLDEncoder->psPredictionEncoder ); + + return 0; +} + +/*------------------------------------------------------------------------------------------* + * Function GetNumGroups() + * + * + *------------------------------------------------------------------------------------------*/ + +Word32 GetNumGroups( LCLDEncoder *psLCLDEncoder ) +{ + return psLCLDEncoder->piNumGroups[0]; +} + + +/*------------------------------------------------------------------------------------------* + * Local functions + * + * + *------------------------------------------------------------------------------------------*/ + +enum MSPred_Types +{ + MS_PHASE_AND_PRED = 0, /* LR phase alignment + real-valued M/S prediction */ + MS_PRED_ONLY = 1, /* real-valued M/S prediction */ + MS_PHASE_ONLY = 2 /* LR phase alignment + M/S */ +}; + +enum MS_BS_TYPES +{ + MS_OFF = 0, + MS_ALL = 1, + MS_SOME = 2, + MS_PRED = 3 +}; +static Word32 MSModeCalculation_fx( + const Word32 iNumBlocks, + const Word32 iNumBands, + const Word32 *piBandwidths, + /*float ***pppfReal, + float ***pppfImag,*/ + Word32 ***pppfReal_fx, + Word32 ***pppfImag_fx, + Word16 Q_in, + Word32 *piMSMode, + Word32 *piLRPhaseDiffs, + Word32 *piMSPredCoefs, + const Word32 iAllowSidePred, + const Word32 iRealOnlyOut, + Word32 *piMSFlags ) +{ + Word32 b; + Word32 iFBOffset; + Word32 iNumMSBands; + Word32 iMSPredType; + /*float fMSBitGain = 0.0f; + float pfMSPredBitGain[3] = { 0.0f }; + float fPred;*/ + Word32 fMSBitGain_fx = 0; + Word32 pfMSPredBitGain_fx[3] = { 0 }; + Word32 fPred_fx; + Word32 piMSPredFlags0[MAX_BANDS] = { 0 }; + Word32 piMSPredFlags1[MAX_BANDS] = { 0 }; + Word32 piMSPredFlags2[MAX_BANDS] = { 0 }; + Word32 *ppiMSPredFlags[3]; + Word32 piMSPredCoefs0[MAX_BANDS] = { 0 }; + Word32 piMSPredCoefs1[MAX_BANDS] = { 0 }; + Word32 piMSPredCoefs2[MAX_BANDS] = { 0 }; + Word32 *ppiMSPredCoefs[3]; + Word32 piMSPredPhase0[MAX_BANDS] = { 0 }; + Word32 piMSPredPhase1[MAX_BANDS] = { 0 }; + Word32 piMSPredPhase2[MAX_BANDS] = { 0 }; + Word32 *ppiMSPredPhase[3]; + Word32 iMsInfoBits; + Word32 piMsPredInfoBits[3] = { 0 }; + + // const float feps = 1e-12f; + // float fBitsFactor = 3.32192809488736f; /* = 1/log10(2), from dB/10 to bits assuming 1 bit per log2(SNR) or 1 bit per 3dB SNR */ + const Word32 feps_fx = 1; // is this correct? + move32(); + Word32 fBitsFactor_fx = 1783446565; /* = 1/log10(2) (Q29), from dB/10 to bits assuming 1 bit per log2(SNR) or 1 bit per 3dB SNR */ + move32(); + IF( LT_32( iNumBlocks, LCLD_BLOCKS_PER_FRAME ) ) + { + // fBitsFactor *= ( 0.7f + (float) ( iNumBlocks - 4 ) / (float) ( LCLD_BLOCKS_PER_FRAME - 4 ) * ( 1.0f - 0.7f ) ); /* Tuning for relatively higher side rate due to shorter frame length */ + fBitsFactor_fx = Mpy_32_32( fBitsFactor_fx, L_add( 1503238553, W_extract_l( W_mult0_32_32( L_sub( iNumBlocks, 4 ), 596523235 ) ) ) ); /* Tuning for relatively higher side rate due to shorter frame length */ + } + + ppiMSPredFlags[0] = piMSPredFlags0; + move32(); + ppiMSPredFlags[1] = piMSPredFlags1; + move32(); + ppiMSPredFlags[2] = piMSPredFlags2; + move32(); + ppiMSPredCoefs[0] = piMSPredCoefs0; + move32(); + ppiMSPredCoefs[1] = piMSPredCoefs1; + move32(); + ppiMSPredCoefs[2] = piMSPredCoefs2; + move32(); + ppiMSPredPhase[0] = piMSPredPhase0; + move32(); + ppiMSPredPhase[1] = piMSPredPhase1; + move32(); + ppiMSPredPhase[2] = piMSPredPhase2; + move32(); + *piMSMode = MS_OFF; + move32(); + iFBOffset = 0; + move32(); + iNumMSBands = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 n; + /*float fLeftEnergy; + float fRightEnergy; + float fMidEnergy; + float fSideEnergy; + float fLRRatio; + float fMSRatio; + float pfMSPredRatio[3] = { 0.0f }; + float fMidEnergyPred; + float fSideEnergyPred; + float fLRCovReal = 0.0f; + float fLRCovImag = 0.0f;*/ + Word32 fLeftEnergy_fx; + Word32 fRightEnergy_fx; + Word32 fMidEnergy_fx; + Word32 fSideEnergy_fx; + Word64 fLeftEnergy_fx64; + Word64 fRightEnergy_fx64; + Word64 fMidEnergy_fx64; + Word64 fSideEnergy_fx64; + Word32 fLRRatio_fx; + Word32 fMSRatio_fx; + Word32 pfMSPredRatio_fx[3] = { 0 }; + Word32 fMidEnergyPred_fx; + Word32 fSideEnergyPred_fx; + Word32 fLRCovReal_fx = 0; + Word32 fLRCovImag_fx = 0; + Word64 fLRCovReal_fx64 = 0; + Word64 fLRCovImag_fx64 = 0; + Word32 iPhase; + Word32 iPred; + Word32 tabIdx = 0; + // float fNumLines = (float)(iRealOnlyOut == 1 ? iNumBlocks * piBandwidths[b] * 4 : iNumBlocks * piBandwidths[b] * 2); /* per band per channel */ + // float fLevelToSMRdBFactor = (float) c_aiDefaultTheta48[b] / (float) ( 1 << PERCEPTUAL_MODEL_SLGAIN_SHIFT ); /* frequency dependent SMR slope in psy model */ + Word32 fNumLines_fx = iRealOnlyOut == 1 ? L_shl( iNumBlocks * piBandwidths[b], 2 ) : L_shl( iNumBlocks * piBandwidths[b], 1 ); /* per band per channel */ + Word32 fLevelToSMRdBFactor_fx = L_shl( c_aiDefaultTheta48[b], 23 ); /* frequency dependent SMR slope in psy model Q23:sub(Q31, PERCEPTUAL_MODEL_SLGAIN_SHIFT) */ + fLeftEnergy_fx = 0; + fRightEnergy_fx = 0; + fMidEnergy_fx = 0; + fSideEnergy_fx = 0; + fLeftEnergy_fx64 = 0; + fRightEnergy_fx64 = 0; + fMidEnergy_fx64 = 0; + fSideEnergy_fx64 = 0; + Word16 Q_en_tmp = 63; + + FOR( n = 0; n < piBandwidths[b]; n++ ) + { + Word32 k; + FOR( k = 0; k < iNumBlocks; k++ ) + { + /*float fMidReal; + float fMidImag; + float fSideReal; + float fSideImag;*/ + Word32 fMidReal_fx; + Word32 fMidImag_fx; + Word32 fSideReal_fx; + Word32 fSideImag_fx; + + // fMidReal = 0.5f * ( pppfReal[0][k][iFBOffset] + pppfReal[1][k][iFBOffset] ); + fMidReal_fx = L_shr( L_add( pppfReal_fx[0][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), 1 ); + // fMidImag = 0.5f * ( pppfImag[0][k][iFBOffset] + pppfImag[1][k][iFBOffset] ); + fMidImag_fx = L_shr( L_add( pppfImag_fx[0][k][iFBOffset], pppfImag_fx[1][k][iFBOffset] ), 1 ); + // fSideReal = 0.5f * ( pppfReal[0][k][iFBOffset] - pppfReal[1][k][iFBOffset] ); + fSideReal_fx = L_shr( L_sub( pppfReal_fx[0][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), 1 ); + // fSideImag = 0.5f * ( pppfImag[0][k][iFBOffset] - pppfImag[1][k][iFBOffset] ); + fSideImag_fx = L_shr( L_sub( pppfImag_fx[0][k][iFBOffset], pppfImag_fx[1][k][iFBOffset] ), 1 ); + + // fLeftEnergy += ( pppfReal[0][k][iFBOffset] * pppfReal[0][k][iFBOffset] + pppfImag[0][k][iFBOffset] * pppfImag[0][k][iFBOffset] ); + fLeftEnergy_fx64 = W_add( fLeftEnergy_fx64, W_add( W_mult0_32_32( pppfReal_fx[0][k][iFBOffset], pppfReal_fx[0][k][iFBOffset] ), W_mult0_32_32( pppfImag_fx[0][k][iFBOffset], pppfImag_fx[0][k][iFBOffset] ) ) ); + // fRightEnergy += ( pppfReal[1][k][iFBOffset] * pppfReal[1][k][iFBOffset] + pppfImag[1][k][iFBOffset] * pppfImag[1][k][iFBOffset] ); + fRightEnergy_fx64 = W_add( fRightEnergy_fx64, W_add( W_mult0_32_32( pppfReal_fx[1][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), W_mult0_32_32( pppfImag_fx[1][k][iFBOffset], pppfImag_fx[1][k][iFBOffset] ) ) ); + // fMidEnergy += ( fMidReal * fMidReal + fMidImag * fMidImag ); + fMidEnergy_fx64 = W_add( fMidEnergy_fx64, W_add( W_mult0_32_32( fMidReal_fx, fMidReal_fx ), W_mult0_32_32( fMidImag_fx, fMidImag_fx ) ) ); + // fSideEnergy += ( fSideReal * fSideReal + fSideImag * fSideImag ); + fSideEnergy_fx64 = W_add( fSideEnergy_fx64, W_add( W_mult0_32_32( fSideReal_fx, fSideReal_fx ), W_mult0_32_32( fSideImag_fx, fSideImag_fx ) ) ); + + // fLRCovReal += ( pppfReal[0][k][iFBOffset] * pppfReal[1][k][iFBOffset] + pppfImag[0][k][iFBOffset] * pppfImag[1][k][iFBOffset] ); + fLRCovReal_fx64 = W_add( fLRCovReal_fx64, W_add( W_mult0_32_32( pppfReal_fx[0][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), W_mult0_32_32( pppfImag_fx[0][k][iFBOffset], pppfImag_fx[1][k][iFBOffset] ) ) ); + // fLRCovImag += ( pppfImag[0][k][iFBOffset] * pppfReal[1][k][iFBOffset] - pppfImag[1][k][iFBOffset] * pppfReal[0][k][iFBOffset] ); + fLRCovImag_fx64 = W_add( fLRCovImag_fx64, W_sub( W_mult0_32_32( pppfImag_fx[0][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), W_mult0_32_32( pppfImag_fx[1][k][iFBOffset], pppfReal_fx[0][k][iFBOffset] ) ) ); + } + + iFBOffset++; + } + Q_en_tmp = min( Q_en_tmp, W_norm( fLeftEnergy_fx64 ) ); + Q_en_tmp = min( Q_en_tmp, W_norm( fRightEnergy_fx64 ) ); + Q_en_tmp = min( Q_en_tmp, W_norm( fMidEnergy_fx64 ) ); + Q_en_tmp = min( Q_en_tmp, W_norm( fSideEnergy_fx64 ) ); + Q_en_tmp = min( Q_en_tmp, W_norm( fLRCovReal_fx64 ) ); + Q_en_tmp = min( Q_en_tmp, W_norm( fLRCovImag_fx64 ) ); + Q_en_tmp = sub( Q_en_tmp, 2 ); + fLeftEnergy_fx = W_extract_h( W_shl( fLeftEnergy_fx64, Q_en_tmp ) ); + fRightEnergy_fx = W_extract_h( W_shl( fRightEnergy_fx64, Q_en_tmp ) ); + fMidEnergy_fx = W_extract_h( W_shl( fMidEnergy_fx64, Q_en_tmp ) ); + fSideEnergy_fx = W_extract_h( W_shl( fSideEnergy_fx64, Q_en_tmp ) ); + fLRCovReal_fx = W_extract_h( W_shl( fLRCovReal_fx64, Q_en_tmp ) ); + fLRCovImag_fx = W_extract_h( W_shl( fLRCovImag_fx64, Q_en_tmp ) ); + Word16 Q_en = add( shl( Q_in, 1 ), sub( Q_en_tmp, 32 ) ) /*2 * Q_in - 31 - 2*/; + /* M/S prediction without phase alignment*/ + // fPred = 0.25f * ( fLeftEnergy - fRightEnergy ) / ( fMidEnergy + feps ); + // iPred = quantPred(fPred); + // fPred = dequantPred(iPred); + Word16 exp; + fPred_fx = BASOP_Util_Divide3232_Scale( L_sub( fLeftEnergy_fx, fRightEnergy_fx ), L_add( fMidEnergy_fx, feps_fx ), &exp ); + exp = sub( exp, 2 ); //*0.25f + fPred_fx = L_shl( fPred_fx, 16 ); + iPred = quantPred_fx( fPred_fx, exp ); + fPred_fx = dequantPred_fx( iPred ); // Q31 + // fSideEnergyPred = fSideEnergy + ( fPred * fPred * fMidEnergy - 2.0f * fPred * 0.25f * ( fLeftEnergy - fRightEnergy ) ); + fSideEnergyPred_fx = L_add( fSideEnergy_fx, + L_sub( Mpy_32_32( Mpy_32_32( fPred_fx, fPred_fx ), fMidEnergy_fx ), + L_shr( Mpy_32_32( fPred_fx, L_sub( fLeftEnergy_fx, fRightEnergy_fx ) ), 1 ) ) ); + fSideEnergyPred_fx = max( fSideEnergyPred_fx, 0 ); + + ppiMSPredCoefs[MS_PRED_ONLY][b] = iPred; + move32(); + ppiMSPredPhase[MS_PRED_ONLY][b] = 0; + move32(); + // pfMSPredRatio[MS_PRED_ONLY] = log10f( ( fMidEnergy + feps ) / ( fSideEnergyPred + feps ) ); + pfMSPredRatio_fx[MS_PRED_ONLY] = Mpy_32_32( L_sub( BASOP_Util_Log2( L_add( fMidEnergy_fx, feps_fx ) ), BASOP_Util_Log2( L_add( fSideEnergyPred_fx, feps_fx ) ) ), LOG10_2_FX ); // Q25 + // printf("%f ", (float)pfMSPredRatio_fx[MS_PRED_ONLY] / (1 << 25)); + + /* Phase alignment*/ + iPhase = 0; + move32(); + // if ( fLRCovReal * fLRCovReal + fLRCovImag * fLRCovImag > 0.5f * fLeftEnergy * fRightEnergy ) + IF( GT_32( L_add( Mpy_32_32( fLRCovReal_fx, fLRCovReal_fx ), Mpy_32_32( fLRCovImag_fx, fLRCovImag_fx ) ), L_shr( Mpy_32_32( fLeftEnergy_fx, fRightEnergy_fx ), 1 ) ) ) + { + // float fPhase = atan2f( fLRCovImag, fLRCovReal ); + Word32 fPhase_fx = BASOP_util_atan2( fLRCovImag_fx, fLRCovReal_fx, 0 ); + exp = sub( 18, norm_l( fPhase_fx ) ); + fPhase_fx = L_shl( fPhase_fx, norm_l( fPhase_fx ) ); // Q31 + // iPhase = quantPhase( fPhase ); + iPhase = quantPhase_fx( fPhase_fx, exp ); + } + + /* adjust covariance */ + tabIdx = L_sub( iPhase, PHASE_MIN_VAL ); + // cplxmult( &fLRCovReal, &fLRCovImag, c_afRotRealImag[tabIdx][0], -c_afRotRealImag[tabIdx][1] ); + cplxmult_fx( &fLRCovReal_fx, &fLRCovImag_fx, c_afRotRealImag_fx[tabIdx][0], -c_afRotRealImag_fx[tabIdx][1] ); + + /* compute MS prediction coefficient based on adjusted covariance */ + // fMidEnergyPred = 0.25f * ( fLeftEnergy + fRightEnergy + 2.0f * fLRCovReal ); + fMidEnergyPred_fx = L_add( L_add( L_shr_r( fLeftEnergy_fx, 2 ), L_shr_r( fRightEnergy_fx, 2 ) ), L_shr( fLRCovReal_fx, 1 ) ); // Q_en + // fSideEnergyPred = 0.25f * ( fLeftEnergy + fRightEnergy - 2.0f * fLRCovReal ); + fSideEnergyPred_fx = L_sub( L_add( L_shr_r( fLeftEnergy_fx, 2 ), L_shr_r( fRightEnergy_fx, 2 ) ), L_shr( fLRCovReal_fx, 1 ) ); // Q_en + fSideEnergyPred_fx = L_max( fSideEnergyPred_fx, 0 ); + + /* M/S with LR phase alignment but without prediction */ + ppiMSPredCoefs[MS_PHASE_ONLY][b] = 0; + move32(); + ppiMSPredPhase[MS_PHASE_ONLY][b] = iPhase; + move32(); + // pfMSPredRatio[MS_PHASE_ONLY] = log10f( ( fMidEnergyPred + feps ) / ( fSideEnergyPred + feps ) ); + pfMSPredRatio_fx[MS_PHASE_ONLY] = Mpy_32_32( L_sub( BASOP_Util_Log2( L_add( fMidEnergyPred_fx, feps_fx ) ), BASOP_Util_Log2( L_add( fSideEnergyPred_fx, feps_fx ) ) ), LOG10_2_FX ); // Q25 + // printf("%f ", (float)pfMSPredRatio_fx[MS_PHASE_ONLY] / (1 << 25)); + + /* M/S with LR phase alignment and prediction */ + // fPred = fMidEnergyPred == 0.0f ? 0.0f : 0.25f * ( fLeftEnergy - fRightEnergy ) / fMidEnergyPred; + fPred_fx = fMidEnergyPred_fx == 0 ? 0 : BASOP_Util_Divide3232_Scale( L_sub( fLeftEnergy_fx, fRightEnergy_fx ), fMidEnergyPred_fx, &exp ); + exp = sub( exp, 2 ); //*0.25f + fPred_fx = L_shl( fPred_fx, 16 ); + // iPred = quantPred( fPred ); + iPred = quantPred_fx( fPred_fx, exp ); + // fPred = dequantPred( iPred ); + fPred_fx = dequantPred_fx( iPred ); + // fSideEnergyPred += ( fPred * fPred * fMidEnergyPred - 2.0f * fPred * 0.25f * ( fLeftEnergy - fRightEnergy ) ); + fSideEnergyPred_fx = L_add( fSideEnergyPred_fx, + L_sub( Mpy_32_32( Mpy_32_32( fPred_fx, fPred_fx ), fMidEnergyPred_fx ), + L_shr( Mpy_32_32( fPred_fx, L_sub( fLeftEnergy_fx, fRightEnergy_fx ) ), 1 ) ) ); + fSideEnergyPred_fx = max( fSideEnergyPred_fx, 0 ); + /* -= fPred * fPred * fMidEnergyPred doesn't work because fPred is quantized and does not match MS/MM exactly */ + ppiMSPredCoefs[MS_PHASE_AND_PRED][b] = iPred; + move32(); + ppiMSPredPhase[MS_PHASE_AND_PRED][b] = iPhase; + move32(); + // pfMSPredRatio[MS_PHASE_AND_PRED] = log10f( ( fMidEnergyPred + feps ) / ( fSideEnergyPred + feps ) ); + pfMSPredRatio_fx[MS_PHASE_AND_PRED] = Mpy_32_32( L_sub( BASOP_Util_Log2( L_add( fMidEnergyPred_fx, feps_fx ) ), BASOP_Util_Log2( L_add( fSideEnergyPred_fx, feps_fx ) ) ), LOG10_2_FX ); // Q25 + // printf("%f ", (float)pfMSPredRatio_fx[MS_PHASE_AND_PRED] / (1 << 25)); + + /* Plain M/S */ + // fLeftEnergy = log10f( fLeftEnergy + feps ); + exp = sub( 31, Q_en ); // 31 - Q + fLeftEnergy_fx = Mpy_32_32( L_add( BASOP_Util_Log2( L_add( fLeftEnergy_fx, feps_fx ) ), L_shl( exp, 25 ) ), LOG10_2_FX ); // Q25 + // fRightEnergy = log10f( fRightEnergy + feps ); + fRightEnergy_fx = Mpy_32_32( L_add( BASOP_Util_Log2( L_add( fRightEnergy_fx, feps_fx ) ), L_shl( exp, 25 ) ), LOG10_2_FX ); // Q25 + // fMidEnergy = log10f( fMidEnergy + feps ); + fMidEnergy_fx = Mpy_32_32( L_add( BASOP_Util_Log2( L_add( fMidEnergy_fx, feps_fx ) ), L_shl( exp, 25 ) ), LOG10_2_FX ); // Q25 + // fSideEnergy = log10f( fSideEnergy + feps ); + fSideEnergy_fx = Mpy_32_32( L_add( BASOP_Util_Log2( L_add( fSideEnergy_fx, feps_fx ) ), L_shl( exp, 25 ) ), LOG10_2_FX ); // Q25 + + // fLRRatio = ( fLeftEnergy > fRightEnergy ? fLeftEnergy - fRightEnergy : fRightEnergy - fLeftEnergy ); + fLRRatio_fx = ( fLeftEnergy_fx > fRightEnergy_fx ? L_sub( fLeftEnergy_fx, fRightEnergy_fx ) : L_sub( fRightEnergy_fx, fLeftEnergy_fx ) ); // Q25 + // fMSRatio = ( fMidEnergy > fSideEnergy ? fMidEnergy - fSideEnergy : fSideEnergy - fMidEnergy ); + fMSRatio_fx = ( fMidEnergy_fx > fSideEnergy_fx ? L_sub( fMidEnergy_fx, fSideEnergy_fx ) : L_sub( fSideEnergy_fx, fMidEnergy_fx ) ); // Q25 + + // if ( fMSRatio > fLRRatio ) + IF( GT_32( fMSRatio_fx, fLRRatio_fx ) ) + { + iNumMSBands++; + piMSFlags[b] = 1; + move32(); + // fMSBitGain += fNumLines * ( fMSRatio - fLRRatio ) * fLevelToSMRdBFactor * fBitsFactor; + fMSBitGain_fx = L_add( fMSBitGain_fx, W_extract_l( W_shr( W_mult0_32_32( fNumLines_fx, Mpy_32_32( Mpy_32_32( L_sub( fMSRatio_fx, fLRRatio_fx ), fLevelToSMRdBFactor_fx ), fBitsFactor_fx ) ), 7 ) ) ); // Q16 + } + ELSE + { + piMSFlags[b] = 0; + move32(); + } + piLRPhaseDiffs[b] = 0; + move32(); + piMSPredCoefs[b] = 0; + move32(); + + /* MSPred bit gains based on increase of level ratio compared to L/R ratio and the level dependent psy-model */ + FOR( iMSPredType = 0; iMSPredType < 3; iMSPredType++ ) + { + // if ( pfMSPredRatio[iMSPredType] > fLRRatio ) + IF( GT_32( pfMSPredRatio_fx[iMSPredType], fLRRatio_fx ) ) + { + ppiMSPredFlags[iMSPredType][b] = 1; + move32(); + // pfMSPredBitGain[iMSPredType] += fNumLines * ( pfMSPredRatio[iMSPredType] - fLRRatio ) * fLevelToSMRdBFactor * fBitsFactor; + pfMSPredBitGain_fx[iMSPredType] = L_add( pfMSPredBitGain_fx[iMSPredType], + W_extract_l( W_shr( W_mult0_32_32( fNumLines_fx, + Mpy_32_32( Mpy_32_32( L_sub( pfMSPredRatio_fx[iMSPredType], fLRRatio_fx ), fLevelToSMRdBFactor_fx ), + fBitsFactor_fx ) ), + 7 ) ) ); // Q16 + } + } + } + Word16 q_fMSBitGain_fx = Q16; + move16(); + Word16 q_pfMSPredBitGain_fx = Q16; // Q23-7 + move16(); + /* remove signalling cost from bit gains */ + FOR( iMSPredType = 0; iMSPredType < 3; iMSPredType++ ) + { + piMsPredInfoBits[iMSPredType] = CountMSBits( iNumBands, MS_PRED, ppiMSPredFlags[iMSPredType], ppiMSPredPhase[iMSPredType], ppiMSPredCoefs[iMSPredType] ); + // pfMSPredBitGain[iMSPredType] = max( pfMSPredBitGain[iMSPredType] - piMsPredInfoBits[iMSPredType], 0.0f ); + pfMSPredBitGain_fx[iMSPredType] = max( pfMSPredBitGain_fx[iMSPredType] - L_shl( piMsPredInfoBits[iMSPredType], q_pfMSPredBitGain_fx ), 0 ); + } + + /* find the best M/S Pred type */ + IF( EQ_32( iRealOnlyOut, 1 ) ) + { + iMSPredType = MS_PRED_ONLY; + move32(); + } + ELSE + { + iMSPredType = MS_PHASE_AND_PRED; + move32(); + // iMSPredType = ( pfMSPredBitGain[MS_PRED_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PRED_ONLY : iMSPredType ); + iMSPredType = ( pfMSPredBitGain_fx[MS_PRED_ONLY] > pfMSPredBitGain_fx[iMSPredType] ? MS_PRED_ONLY : iMSPredType ); + // iMSPredType = ( pfMSPredBitGain[MS_PHASE_ONLY] > pfMSPredBitGain[iMSPredType] ? MS_PHASE_ONLY : iMSPredType ); + iMSPredType = ( pfMSPredBitGain_fx[MS_PHASE_ONLY] > pfMSPredBitGain_fx[iMSPredType] ? MS_PHASE_ONLY : iMSPredType ); + } + + /* plain M/S */ + iMsInfoBits = CountMSBits( iNumBands, MS_SOME, piMSFlags, NULL, NULL ); + // fMSBitGain = max( fMSBitGain - iMsInfoBits, 0.0f ); + fMSBitGain_fx = L_max( L_sub( fMSBitGain_fx, L_shl( iMsInfoBits, q_fMSBitGain_fx ) ), 0 ); // Q_en -2 + // if ( iAllowSidePred && pfMSPredBitGain[iMSPredType] > 1.1f * fMSBitGain ) + test(); + IF( iAllowSidePred && GT_32( L_shr_r( pfMSPredBitGain_fx[iMSPredType], sub( q_pfMSPredBitGain_fx, q_fMSBitGain_fx ) ), L_add( fMSBitGain_fx, Mpy_32_32( fMSBitGain_fx, 214748364 ) ) ) ) + { + *piMSMode = MS_PRED; + move32(); + iNumMSBands = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + piMSFlags[b] = ppiMSPredFlags[iMSPredType][b]; + IF( EQ_32( piMSFlags[b], 1 ) ) + { + piMSPredCoefs[b] = ppiMSPredCoefs[iMSPredType][b]; + move32(); + piLRPhaseDiffs[b] = ppiMSPredPhase[iMSPredType][b]; + move32(); + iNumMSBands++; + } + ELSE + { + piMSPredCoefs[b] = 0; + move32(); + piLRPhaseDiffs[b] = 0; + move32(); + } + } + } + ELSE IF( EQ_32( iNumMSBands, iNumBands ) ) + { + *piMSMode = MS_ALL; + move32(); + } + ELSE IF( GT_32( iNumMSBands, 0 ) ) + { + *piMSMode = MS_SOME; + move32(); + } + ELSE + { + *piMSMode = MS_OFF; + move32(); + } +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + int32_t iActualInfoBits = CountMSBits( iNumBands, *piMSMode, piMSFlags, piLRPhaseDiffs, piMSPredCoefs ); + if ( !fid ) + fid = fopen( "ms_info_bits.txt", "wt" ); + fprintf( fid, "%d %d %d %d %d\n", iMsInfoBits, piMsPredInfoBits[MS_PHASE_AND_PRED], piMsPredInfoBits[MS_PRED_ONLY], piMsPredInfoBits[MS_PHASE_ONLY], iActualInfoBits ); + } +#endif + IF( NE_32( *piMSMode, MS_OFF ) ) + { + iFBOffset = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + IF( EQ_32( piMSFlags[b], 1 ) ) + { + Word32 n; + Word32 phaseIdx; + phaseIdx = L_sub( piLRPhaseDiffs[b], PHASE_MIN_VAL ); + // fPred = dequantPred( piMSPredCoefs[b] ); + fPred_fx = dequantPred_fx( piMSPredCoefs[b] ); // Q31 + FOR( n = 0; n < piBandwidths[b]; n++ ) + { + Word32 k; + FOR( k = 0; k < iNumBlocks; k++ ) + { + /*float fMidReal; + float fMidImag; + float fSideReal; + float fSideImag;*/ + Word32 fMidReal_fx; + Word32 fMidImag_fx; + Word32 fSideReal_fx; + Word32 fSideImag_fx; + + IF( EQ_32( *piMSMode, MS_PRED ) ) + { + // cplxmult( &pppfReal[1][k][iFBOffset], &pppfImag[1][k][iFBOffset], c_afRotRealImag[phaseIdx][0], c_afRotRealImag[phaseIdx][1] ); + cplxmult_fx( &pppfReal_fx[1][k][iFBOffset], &pppfImag_fx[1][k][iFBOffset], c_afRotRealImag_fx[phaseIdx][0], c_afRotRealImag_fx[phaseIdx][1] ); + } + + // fMidReal = 0.5f * ( pppfReal[0][k][iFBOffset] + pppfReal[1][k][iFBOffset] ); + fMidReal_fx = L_shr( L_add( pppfReal_fx[0][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), 1 ); + // fMidImag = 0.5f * ( pppfImag[0][k][iFBOffset] + pppfImag[1][k][iFBOffset] ); + fMidImag_fx = L_shr( L_add( pppfImag_fx[0][k][iFBOffset], pppfImag_fx[1][k][iFBOffset] ), 1 ); + // fSideReal = 0.5f * ( pppfReal[0][k][iFBOffset] - pppfReal[1][k][iFBOffset] ); + fSideReal_fx = L_shr( L_sub( pppfReal_fx[0][k][iFBOffset], pppfReal_fx[1][k][iFBOffset] ), 1 ); + // fSideImag = 0.5f * ( pppfImag[0][k][iFBOffset] - pppfImag[1][k][iFBOffset] ); + fSideImag_fx = L_shr( L_sub( pppfImag_fx[0][k][iFBOffset], pppfImag_fx[1][k][iFBOffset] ), 1 ); + + IF( EQ_32( *piMSMode, MS_PRED ) ) + { + // fSideReal -= fPred * fMidReal; + fSideReal_fx = L_sub( fSideReal_fx, Mpy_32_32( fPred_fx, fMidReal_fx ) ); + // fSideImag -= fPred * fMidImag; + fSideImag_fx = L_sub( fSideImag_fx, Mpy_32_32( fPred_fx, fMidImag_fx ) ); + } + + pppfReal_fx[0][k][iFBOffset] = fMidReal_fx; + move32(); + pppfReal_fx[1][k][iFBOffset] = fSideReal_fx; + move32(); + pppfImag_fx[0][k][iFBOffset] = fMidImag_fx; + move32(); + pppfImag_fx[1][k][iFBOffset] = fSideImag_fx; + move32(); + } + iFBOffset++; + } + } + ELSE + { + iFBOffset = L_add( iFBOffset, piBandwidths[b] ); + } + } + } +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + if ( !fid ) + fid = fopen( "ms_enc.txt", "wt" ); + writeMSPred( piLRPhaseDiffs, piMSPredCoefs, *piMSMode, iNumMSBands, iNumBands, fid, piMSFlags ); + } +#endif + IF( EQ_32( *piMSMode, MS_PRED ) ) + { + /* Differential Coding of Phase Data*/ + PrepEncode( piLRPhaseDiffs, piMSFlags, iNumBands ); + PrepEncode( piMSPredCoefs, piMSFlags, iNumBands ); +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid; + if ( !fid ) + fid = fopen( "ms_pred_enc.txt", "wt" ); + writeMSPred( piLRPhaseDiffs, piMSPredCoefs, *piMSMode, iNumMSBands, iNumBands, fid, piMSFlags ); + } +#endif + /* Differential Coding*/ + EncodePhase( piLRPhaseDiffs, iNumMSBands, PHASE_DIFF_DIM ); + EncodePredCoef( piMSPredCoefs, iNumMSBands ); + } + + return iNumMSBands; +} +static void RemoveRMSEnvelope( + const Word32 iNumBands, + const Word32 *piBandwidths, + const Word32 iNumGroups, + const Word32 *piGroupLengths, + Word32 **ppiRMSEnvelope, + Word32 **ppfReal_fx, + Word32 **ppfImag_fx ) +{ + Word32 k, n, b, iFBOffset, m, iRMSEnv; + Word32 iBlockOffset; + Word32 fGain_fx; + Word16 fGain_exp; + iBlockOffset = 0; + move32(); + Word64 tmp; + FOR( n = 0; n < iNumGroups; n++ ) + { + FOR( k = 0; k < piGroupLengths[n]; k++ ) + { + iFBOffset = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + iRMSEnv = ppiRMSEnvelope[n][b]; + IF( EQ_32( L_add( ENV_RECONSTRUCT_TABLE_CENTER, iRMSEnv ) % 2, 0 ) ) + { + fGain_fx = 1073741824; // 2 ^ 30 + move32(); + } + ELSE + { + fGain_fx = 1518500249; // sqrt(2) * 2 ^ 30 + move32(); + } + fGain_exp = c_afRMSEnvReconstructTable_exp[ENV_RECONSTRUCT_TABLE_CENTER - iRMSEnv]; + move16(); + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + tmp = W_mult_32_32( fGain_fx, ppfReal_fx[iBlockOffset][iFBOffset] ); + tmp = W_shr( tmp, sub( fGain_exp, 8 ) ); // Q to (input_q -9) + ppfReal_fx[iBlockOffset][iFBOffset] = W_extract_l( tmp ); + move32(); + tmp = W_mult_32_32( fGain_fx, ppfImag_fx[iBlockOffset][iFBOffset] ); + tmp = W_shr( tmp, sub( fGain_exp, 8 ) ); // Q to (input_q -9) + ppfImag_fx[iBlockOffset][iFBOffset] = W_extract_l( tmp ); + move32(); + iFBOffset++; + } + } + iBlockOffset++; + } + } + + return; +} +static void QuantizeSpectrumDPCM_Opt( + const Word32 iNumGroups, + const Word32 *piGroupLengths, + const Word32 iNumBands, + const Word32 *piBandwidths, + Word32 **ppiAlloc, + Word32 **ppfReal_fx, + Word32 **ppfImag_fx, + Word16 q_final, + Word32 **ppiQReal, + Word32 **ppiQImag, + Word32 **ppiSignReal, + Word32 **ppiSignImag, + Word32 iNumSubSets, + Word32 iSubSetId, + Word32 *piPredEnable, + Word32 *pfA1Real_fx, + Word32 *pfA1Imag_fx, + Word32 *pfPredStateReal_fx, + Word32 *pfPredStateImag_fx ) +{ + Word32 b, n; + Word32 iFBOffset; + Word32 k, iAlloc; + Word32 iMaxQuantVal_fx; + Word32 fSCFGain_fx, fInvSCFGain_fx; + iFBOffset = 0; + Word32 ppiQReal_fx, ppiQImag_fx; + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 m; + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + Word32 iBlockOffset = 0; + IF( EQ_32( piPredEnable[iFBOffset], 1 ) ) + { + Word32 fReal_fx; + Word32 fImag_fx; + Word32 iSubset = iFBOffset % iNumSubSets; + Word32 fPrevReal_fx = 0; + Word32 fPrevImag_fx = 0; + IF( NE_32( iSubset, iSubSetId ) ) + { + /* run predictors across sub-frames */ + fPrevReal_fx = pfPredStateReal_fx[iFBOffset]; + move32(); + fPrevImag_fx = pfPredStateImag_fx[iFBOffset]; + move32(); + } + FOR( n = 0; n < iNumGroups; n++ ) + { + iAlloc = ppiAlloc[n][b]; + iMaxQuantVal_fx = c_aiQuantMaxValues_fx[iAlloc]; + fSCFGain_fx = c_afScaleFactor_fx[iAlloc]; + fInvSCFGain_fx = c_afInvScaleFactor_fx[iAlloc]; + FOR( k = 0; k < piGroupLengths[n]; k++ ) + { + /* prediction */ + fReal_fx = L_sub( Mpy_32_32( pfA1Real_fx[iFBOffset], fPrevReal_fx ), Mpy_32_32( pfA1Imag_fx[iFBOffset], fPrevImag_fx ) ); + fImag_fx = L_add( Mpy_32_32( pfA1Real_fx[iFBOffset], fPrevImag_fx ), Mpy_32_32( pfA1Imag_fx[iFBOffset], fPrevReal_fx ) ); + ppiQReal_fx = Quantize_fx( L_add_sat( L_shr_r_sat( ppfReal_fx[iBlockOffset][iFBOffset], sub( q_final, Q28 ) ), fReal_fx ), /* quantize residual */ + fSCFGain_fx, + &ppiSignReal[iBlockOffset][iFBOffset], + iMaxQuantVal_fx ); + ppiQImag_fx = Quantize_fx( L_add_sat( L_shr_r_sat( ppfImag_fx[iBlockOffset][iFBOffset], sub( q_final, Q28 ) ), fImag_fx ), + fSCFGain_fx, + &ppiSignImag[iBlockOffset][iFBOffset], + iMaxQuantVal_fx ); + ppiQReal[iBlockOffset][iFBOffset] = L_shr( ppiQReal_fx, 21 ); + + ppiQImag[iBlockOffset][iFBOffset] = L_shr( ppiQImag_fx, 21 ); + + ppiQReal_fx = L_shl( ppiQReal[iBlockOffset][iFBOffset], 21 ); + fPrevReal_fx = L_sub( L_shl( UnQuantize_fx( ppiQReal_fx, + fInvSCFGain_fx, + ppiSignReal[iBlockOffset][iFBOffset] ), + 9 ), + fReal_fx ); + /* add prediction to quantized residual = reconstructed sample */ + + ppiQImag_fx = L_shl( ppiQImag[iBlockOffset][iFBOffset], 21 ); + fPrevImag_fx = L_sub( L_shl( UnQuantize_fx( ppiQImag_fx, + fInvSCFGain_fx, + ppiSignImag[iBlockOffset][iFBOffset] ), + 9 ), + fImag_fx ); + iBlockOffset++; + } /* group length */ + } /* groups */ + pfPredStateReal_fx[iFBOffset] = fPrevReal_fx; + move32(); + pfPredStateImag_fx[iFBOffset] = fPrevImag_fx; + move32(); + } /* predEnable */ + ELSE + { /* no prediction */ + FOR( n = 0; n < iNumGroups; n++ ) + { + iAlloc = ppiAlloc[n][b]; + move32(); + iMaxQuantVal_fx = c_aiQuantMaxValues_fx[iAlloc]; + move32(); + fSCFGain_fx = c_afScaleFactor_fx[iAlloc]; + move32(); + fInvSCFGain_fx = c_afInvScaleFactor_fx[iAlloc]; + move32(); + FOR( k = 0; k < piGroupLengths[n]; k++ ) + { + ppiQReal_fx = Quantize_fx( L_shr_r_sat( ppfReal_fx[iBlockOffset][iFBOffset], sub( q_final, Q28 ) ), + fSCFGain_fx, + &ppiSignReal[iBlockOffset][iFBOffset], + iMaxQuantVal_fx ); + ppiQImag_fx = Quantize_fx( L_shr_r_sat( ppfImag_fx[iBlockOffset][iFBOffset], sub( q_final, Q28 ) ), + fSCFGain_fx, + &ppiSignImag[iBlockOffset][iFBOffset], + iMaxQuantVal_fx ); + + ppiQReal[iBlockOffset][iFBOffset] = L_shr( ppiQReal_fx, 21 ); + + ppiQImag[iBlockOffset][iFBOffset] = L_shr( ppiQImag_fx, 21 ); + + iBlockOffset++; + } /* group length */ + } /* groups */ + } /* predEnable */ + iFBOffset++; + } /* bandwidth */ + } +} +static Word32 CountLCLDBits( + const Word32 iNumGroups, + const Word32 *piGroupLengths, + const Word32 iNumBands, + const Word32 *piBandwidths, + const Word32 *piPredEnable, + Word32 **ppiAlloc, + Word32 **ppiQReal, + Word32 **ppiQImag ) +{ + Word32 k, n, b, iFBOffset; + Word32 iBits, iBlockOffest; + Word32 m, iAlloc, iHuffDim, iHuffMod; + + iBits = 0; + move32(); + iBlockOffest = 0; + move32(); + FOR( n = 0; n < iNumGroups; n++ ) + { + FOR( k = 0; k < piGroupLengths[n]; k++ ) + { + iFBOffset = 0; + move32(); + FOR( b = 0; b < iNumBands; b++ ) + { + iAlloc = ppiAlloc[n][b]; + move32(); + + iHuffDim = c_aiHuffmanDim[iAlloc]; + move32(); + iHuffMod = c_aiHuffmanMod[iAlloc]; + move32(); + + IF( GT_32( iAlloc, 0 ) ) + { + const UWord16( *pauiHuffmanTable )[2] = NULL; + const UWord16( *pauiHuffmanTableDPCM )[2] = NULL; + pauiHuffmanTable = c_apauiHuffEncTabels[iAlloc]; + pauiHuffmanTableDPCM = c_apauiHuffEncTabels[ALLOC_TABLE_SIZE + iAlloc]; + FOR( m = 0; m < piBandwidths[b]; m++ ) + { + Word32 iQuantValue1; + Word32 iQuantValue2; + + iQuantValue1 = ppiQReal[iBlockOffest][iFBOffset]; + move32(); + iQuantValue2 = ppiQImag[iBlockOffest][iFBOffset]; + move32(); + + iBits = L_add( iBits, GT_32( iQuantValue1, 0 ) ? 1 : 0 ); /* Sign bit for vals > 0 */ + iBits = L_add( iBits, GT_32( iQuantValue2, 0 ) ? 1 : 0 ); /* Sign bit for vals > 0 */ + + IF( EQ_32( piPredEnable[iFBOffset], 1 ) ) + { + IF( EQ_32( iHuffDim, 2 ) ) + { + iQuantValue1 *= iHuffMod; + iQuantValue1 = L_add( iQuantValue1, iQuantValue2 ); + iBits = L_add( iBits, pauiHuffmanTableDPCM[iQuantValue1][0] ); + } + ELSE + { + iBits = L_add( iBits, pauiHuffmanTableDPCM[iQuantValue1][0] ); + iBits = L_add( iBits, pauiHuffmanTableDPCM[iQuantValue2][0] ); + } + } + ELSE + { + IF( EQ_32( iHuffDim, 2 ) ) + { + iQuantValue1 *= iHuffMod; + iQuantValue1 = L_add( iQuantValue1, iQuantValue2 ); + iBits = L_add( iBits, pauiHuffmanTable[iQuantValue1][0] ); + } + ELSE + { + iBits = L_add( iBits, pauiHuffmanTable[iQuantValue1][0] ); + iBits = L_add( iBits, pauiHuffmanTable[iQuantValue2][0] ); + } + } + + iFBOffset++; + } + } + ELSE + { + iFBOffset = L_add( iFBOffset, piBandwidths[b] ); + } + } + + iBlockOffest++; + } + } + + return iBits; +} + + +/* Currently only the number of bands in frame */ +static Word32 WriteHeaderInformation( + const Word32 iNumBands, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsWritten; + + iBitsWritten = 0; + move32(); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iNumBands, 5 ); + iBitsWritten = L_add( iBitsWritten, 5 ); + + return iBitsWritten; +} + + +static Word32 WriteMSInformation( + const Word32 iNumBands, + const Word32 iMSMode, + const Word32 *piMSFlags, + const Word32 *piLRPhaseDiff, + const Word32 *piMSPredCoef, + Word32 iNumMSPredBands, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsWritten; + Word32 iMSPredAll = (Word32) EQ_32( iNumMSPredBands, iNumBands ); + move32(); +#ifdef DEBUG_WRITE_MS_PRED + Word32 iBitsWrittenTmp = 0; + move32(); +#endif + iBitsWritten = 0; + move32(); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iMSMode, 2 ); + iBitsWritten = L_add( iBitsWritten, 2 ); + + IF( EQ_32( iMSMode, 3 ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iMSPredAll, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + + test(); + test(); + IF( EQ_32( iMSMode, 2 ) || ( EQ_32( iMSMode, 3 ) && !iMSPredAll ) ) + { + Word32 n; + FOR( n = 0; n < iNumBands; n++ ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, piMSFlags[n], 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + } + +#ifdef DEBUG_WRITE_MS_PRED + iBitsWrittenTmp = iBitsWritten; +#endif + IF( EQ_32( iMSMode, 3 ) ) + { + Word32 b; + Word32 anyNonZero; + anyNonZero = 0; + move32(); + FOR( b = 0; b < iNumMSPredBands; b++ ) + { + IF( NE_32( piLRPhaseDiff[b], 0 ) ) + { + anyNonZero = 1; + move32(); + BREAK; + } + } + ISAR_SPLIT_REND_BITStream_write_int32( pBits, anyNonZero, 1 ); + iBitsWritten++; + + IF( anyNonZero ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, L_sub( piLRPhaseDiff[0], PHASE_MIN_VAL ), PHASE_BAND0_BITS ); + iBitsWritten = L_add( iBitsWritten, PHASE_BAND0_BITS ); + FOR( b = 1; b < iNumMSPredBands; b++ ) + { + Word32 tabIdx = L_sub( piLRPhaseDiff[b], ENV_DELTA_MIN ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] ); + iBitsWritten = L_add( iBitsWritten, c_aaiRMSEnvHuffEnc[tabIdx][0] ); + } + } + + anyNonZero = 0; + move32(); + FOR( b = 0; b < iNumMSPredBands; b++ ) + { + IF( NE_32( piMSPredCoef[b], 0 ) ) + { + anyNonZero = 1; + move32(); + BREAK; + } + } + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, anyNonZero, 1 ); + iBitsWritten++; + + IF( anyNonZero ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, L_sub( piMSPredCoef[0], PRED_MIN_VAL ), PRED_BAND0_BITS ); + iBitsWritten = L_add( iBitsWritten, PRED_BAND0_BITS ); + FOR( b = 1; b < iNumMSPredBands; b++ ) + { + Word32 tabIdx = L_sub( piMSPredCoef[b], ENV_DELTA_MIN ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, c_aaiRMSEnvHuffEnc[tabIdx][1], c_aaiRMSEnvHuffEnc[tabIdx][0] ); + iBitsWritten = L_add( iBitsWritten, c_aaiRMSEnvHuffEnc[tabIdx][0] ); + } + } + } +#ifdef DEBUG_WRITE_MS_PRED + { + static FILE *fid = 0; + IF( !fid ) + { + fid = fopen( "ms_pred_bitrate.txt", "wt" ); + } + fprintf( fid, "%f\n", (float) ( ( iBitsWritten - iBitsWrittenTmp ) * ( iMSMode == 3 ) * 50 ) / 1000.0f ); /*kb/s*/ + } +#endif + + return iBitsWritten; +} + + +static Word32 WriteGroupInformation( + const Word32 iChannels, + const Word32 iCommonGrouping, + const Word32 *piNumGroups, + Word32 **ppiGroupLengths, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 c, k, n, iBitsWritten; + + iBitsWritten = 0; + move32(); + test(); + IF( EQ_32( iChannels, 2 ) && EQ_32( iCommonGrouping, 1 ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iCommonGrouping, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + + FOR( n = 0; n < piNumGroups[0]; n++ ) + { + FOR( k = 1; k < ppiGroupLengths[0][n]; k++ ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + IF( LT_32( n, L_sub( piNumGroups[0], 1 ) ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + } + } + ELSE IF( EQ_32( iChannels, 2 ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, iCommonGrouping, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + + FOR( c = 0; c < iChannels; c++ ) + { + FOR( n = 0; n < piNumGroups[c]; n++ ) + { + FOR( k = 1; k < ppiGroupLengths[c][n]; k++ ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + IF( LT_32( n, L_sub( piNumGroups[c], 1 ) ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + } + } + } + ELSE + { + FOR( c = 0; c < iChannels; c++ ) + { + FOR( n = 0; n < piNumGroups[c]; n++ ) + { + FOR( k = 1; k < ppiGroupLengths[c][n]; k++ ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + + IF( LT_32( n, L_sub( piNumGroups[c], 1 ) ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + } + } + } + + return iBitsWritten; +} + + +static Word32 WriteRMSEnvelope( + const Word32 iChannels, + const Word32 *piNumGroups, + const Word32 iNumBands, + Word32 ***pppiRMSEnvelope, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 k, n; + Word32 iBitsWritten; + + iBitsWritten = 0; + move32(); + FOR( n = 0; n < iChannels; n++ ) + { + FOR( k = 0; k < piNumGroups[n]; k++ ) + { + Word32 b; + Word32 iLastRMSVal; + + iLastRMSVal = pppiRMSEnvelope[n][k][0]; + move32(); + iLastRMSVal = GT_32( iLastRMSVal, ENV_MIN ) ? iLastRMSVal : ENV_MIN; + move32(); + iLastRMSVal = LT_32( iLastRMSVal, ENV_MAX ) ? iLastRMSVal : ENV_MAX; + move32(); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, L_sub( iLastRMSVal, ENV_MIN ), ENV0_BITS ); + iBitsWritten = L_add( iBitsWritten, ENV0_BITS ); + + FOR( b = 1; b < iNumBands; b++ ) + { + Word32 iDelta; + + iDelta = L_sub( pppiRMSEnvelope[n][k][b], iLastRMSVal ); + iDelta = GT_32( iDelta, ENV_DELTA_MIN ) ? iDelta : ENV_DELTA_MIN; + move32(); + iDelta = LT_32( iDelta, ENV_DELTA_MAX ) ? iDelta : ENV_DELTA_MAX; + move32(); + iDelta = L_sub( iDelta, ENV_DELTA_MIN ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, c_aaiRMSEnvHuffEnc[iDelta][1], c_aaiRMSEnvHuffEnc[iDelta][0] ); + iBitsWritten = L_add( iBitsWritten, c_aaiRMSEnvHuffEnc[iDelta][0] ); + + iLastRMSVal = pppiRMSEnvelope[n][k][b]; + move32(); + } + } + } + + return iBitsWritten; +} + + +static Word32 WriteAllocInformation( + const Word32 iAllocOffset, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsWritten; + + iBitsWritten = 0; + move32(); + + IF( LT_32( iAllocOffset, MIN_ALLOC_OFFSET ) || GT_32( iAllocOffset, MAX_ALLOC_OFFSET ) ) + { + printf( "Serious error\n" ); + } + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, L_sub( iAllocOffset, MIN_ALLOC_OFFSET ), ALLOC_OFFSET_BITS ); + iBitsWritten = L_add( iBitsWritten, ALLOC_OFFSET_BITS ); + + return iBitsWritten; +} + + +static Word32 WriteLCLDData( + const Word32 *piNumGroups, + Word32 **ppiGroupLengths, + const Word32 iNumBands, + const Word32 iNumChannels, + Word32 **ppiPredEnable, + const Word32 iNumSubSets, + const Word32 iSubSetId, + Word32 ***pppiAlloc, + Word32 ***pppiSignReal, + Word32 ***pppiSignImag, + Word32 ***pppiQReal, + Word32 ***pppiQImag, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word32 iBitsWritten; + Word32 iNumLcldBands = c_aiNumLcldBandsPerBand[iNumBands - 1]; + Word32 s; + Word32 iSet = iSubSetId; + + iBitsWritten = 0; + move32(); + FOR( s = 0; s < iNumSubSets; ( s++, iSet-- ) ) + { + Word32 ch; + IF( LT_32( iSet, 0 ) ) + { + iSet = L_sub( iNumSubSets, 1 ); + } + + FOR( ch = 0; ch < iNumChannels; ch++ ) + { + Word32 iBlockOffest = 0; + move32(); + Word32 n; + FOR( n = 0; n < piNumGroups[ch]; n++ ) + { + Word32 k; + FOR( k = 0; k < ppiGroupLengths[ch][n]; k++ ) + { + Word32 iFBOffset; + FOR( iFBOffset = iSet; iFBOffset < iNumLcldBands; iFBOffset += iNumSubSets ) + { + Word32 b; + Word32 iAlloc; + Word32 iHuffDim; + Word32 iHuffMod; + + b = c_aiBandIdPerLcldBand[iFBOffset]; + move32(); + + iAlloc = pppiAlloc[ch][n][b]; + move32(); + + iHuffDim = c_aiHuffmanDim[iAlloc]; + move32(); + iHuffMod = c_aiHuffmanMod[iAlloc]; + move32(); + + IF( GT_32( iAlloc, 0 ) ) + { + const UWord16( *pauiHuffmanTable )[2] = NULL; + const UWord16( *pauiHuffmanTableDPCM )[2] = NULL; + Word32 iQuantValue1; + Word32 iQuantValue2; + pauiHuffmanTable = c_apauiHuffEncTabels[iAlloc]; + pauiHuffmanTableDPCM = c_apauiHuffEncTabels[ALLOC_TABLE_SIZE + iAlloc]; + + iQuantValue1 = pppiQReal[ch][iBlockOffest][iFBOffset]; + move32(); + iQuantValue2 = pppiQImag[ch][iBlockOffest][iFBOffset]; + move32(); +#ifdef LCLD_HANDLE_PRED_START_SAMPLE + IF( ppiPredEnable[ch][iFBOffset] == 1 && ( iBlockOffest > 0 || iSet != iSubSetId ) ) +#else + IF( EQ_32( ppiPredEnable[ch][iFBOffset], 1 ) ) +#endif + { + IF( EQ_32( iHuffDim, 2 ) ) + { + Word32 iSymbol; + iSymbol = iQuantValue1; + move32(); + iSymbol *= iHuffMod; + iSymbol = L_add( iSymbol, iQuantValue2 ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTableDPCM[iSymbol][1], pauiHuffmanTableDPCM[iSymbol][0] ); + iBitsWritten = L_add( iBitsWritten, pauiHuffmanTableDPCM[iSymbol][0] ); + } + ELSE + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTableDPCM[iQuantValue1][1], pauiHuffmanTableDPCM[iQuantValue1][0] ); + iBitsWritten = L_add( iBitsWritten, pauiHuffmanTableDPCM[iQuantValue1][0] ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTableDPCM[iQuantValue2][1], pauiHuffmanTableDPCM[iQuantValue2][0] ); + iBitsWritten = L_add( iBitsWritten, pauiHuffmanTableDPCM[iQuantValue2][0] ); + } + } + ELSE + { + IF( EQ_32( iHuffDim, 2 ) ) + { + Word32 iSymbol; + iSymbol = iQuantValue1; + move32(); + iSymbol *= iHuffMod; + iSymbol = L_add( iSymbol, iQuantValue2 ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTable[iSymbol][1], pauiHuffmanTable[iSymbol][0] ); + iBitsWritten = L_add( iBitsWritten, pauiHuffmanTable[iSymbol][0] ); + } + ELSE + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTable[iQuantValue1][1], pauiHuffmanTable[iQuantValue1][0] ); + iBitsWritten = L_add( iBitsWritten, pauiHuffmanTable[iQuantValue1][0] ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pauiHuffmanTable[iQuantValue2][1], pauiHuffmanTable[iQuantValue2][0] ); + iBitsWritten = L_add( iBitsWritten, pauiHuffmanTable[iQuantValue2][0] ); + } + } + + IF( GT_32( iQuantValue1, 0 ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pppiSignReal[ch][iBlockOffest][iFBOffset], 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + IF( GT_32( iQuantValue2, 0 ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pppiSignImag[ch][iBlockOffest][iFBOffset], 1 ); + iBitsWritten = L_add( iBitsWritten, 1 ); + } + } + } + iBlockOffest++; + } + } + } + } + + return iBitsWritten; +} +static Word32 ComputeAllocation( + const Word32 iChannels, + const Word32 *piNumGroups, + Word32 **ppiGroupLengths, + const Word32 iNumBands, + const Word32 *piBandwidths, + Word32 ***pppfReal_fx, + Word32 ***pppfImag_fx, + Word16 q_final, + Word32 ***pppiSMR, + const Word32 iAvailableBits, + Word32 *piAllocOffset, + Word32 ***pppiAlloc, + Word32 ***pppiQReal, + Word32 ***pppiQImag, + Word32 ***pppiSignReal, + Word32 ***pppiSignImag, + PredictionEncoder *psPredictionEncoder ) +{ + Word32 iBitsUsed, iDone, iDelta; + Word32 b, k, n; + Word32 iLimitAllocOffset; + + iBitsUsed = ALLOC_OFFSET_BITS; /* Bits used for Alloc Offset */ + move32(); + iDone = 0; + move32(); + iDelta = -MIN_ALLOC_OFFSET; + move32(); + *piAllocOffset = 0; + move32(); + WHILE( EQ_32( iDone, 0 ) ) + { + iBitsUsed = ALLOC_OFFSET_BITS; + move32(); + iLimitAllocOffset = *piAllocOffset; + move32(); + iLimitAllocOffset = GT_32( iLimitAllocOffset, MIN_ALLOC_OFFSET ) ? iLimitAllocOffset : MIN_ALLOC_OFFSET; + iLimitAllocOffset = LT_32( iLimitAllocOffset, MAX_ALLOC_OFFSET ) ? iLimitAllocOffset : MAX_ALLOC_OFFSET; + + FOR( n = 0; n < iChannels; n++ ) + { + FOR( k = 0; k < piNumGroups[n]; k++ ) + { + FOR( b = 0; b < iNumBands; b++ ) + { + Word32 iAlloc; + iAlloc = ( L_shr( L_add( pppiSMR[n][k][b], L_mult0( extract_l( iLimitAllocOffset ), ALLOC_OFFSET_SCALE ) ), 5 ) ); + iAlloc = GT_32( iAlloc, MIN_ALLOC ) ? iAlloc : MIN_ALLOC; + iAlloc = LT_32( iAlloc, MAX_ALLOC ) ? iAlloc : MAX_ALLOC; + pppiAlloc[n][k][b] = iAlloc; + move32(); + } + } + IF( psPredictionEncoder->iNumSubSets > 1 ) + { + mvl2l( psPredictionEncoder->ppfPredStateReal_fx[n], psPredictionEncoder->ppfPredStateRealTmp_fx[n], LCLD_BANDS ); + mvl2l( psPredictionEncoder->ppfPredStateImag_fx[n], psPredictionEncoder->ppfPredStateImagTmp_fx[n], LCLD_BANDS ); + } + + QuantizeSpectrumDPCM_Opt( piNumGroups[n], + (const Word32 *) ppiGroupLengths[n], + iNumBands, + piBandwidths, + pppiAlloc[n], + pppfReal_fx[n], + pppfImag_fx[n], + q_final, + pppiQReal[n], + pppiQImag[n], + pppiSignReal[n], + pppiSignImag[n], + psPredictionEncoder->iNumSubSets, + psPredictionEncoder->iSubSetId, + psPredictionEncoder->ppiPredBandEnable[n], + psPredictionEncoder->ppfA1Real_fx[n], + psPredictionEncoder->ppfA1Imag_fx[n], + psPredictionEncoder->ppfPredStateRealTmp_fx[n], + psPredictionEncoder->ppfPredStateImagTmp_fx[n] ); + iBitsUsed = L_add( iBitsUsed, CountLCLDBits( piNumGroups[n], + (const Word32 *) ppiGroupLengths[n], + iNumBands, + piBandwidths, + (const Word32 *) psPredictionEncoder->ppiPredBandEnable[n], + pppiAlloc[n], + pppiQReal[n], + pppiQImag[n] ) ); + } + + IF( LE_32( *piAllocOffset, MIN_ALLOC_OFFSET ) && GT_32( iBitsUsed, iAvailableBits ) ) + { +#ifdef DEBUG_VERBOSE + printf( "Frame can not be coded with the number of bits available\n" ); +#endif + // iLastError = ENC_ERROR_STREAM_FAILURE; + return -1; + } + ELSE IF( GE_32( *piAllocOffset, MAX_ALLOC_OFFSET ) && LT_32( iBitsUsed, iAvailableBits ) ) + { + *piAllocOffset = MAX_ALLOC_OFFSET; + iDone++; + } + ELSE + { + IF( EQ_32( iDelta, 0 ) && GT_32( iBitsUsed, iAvailableBits ) ) + { + iDelta = 1; + } + ELSE IF( EQ_32( iDelta, 0 ) && LT_32( iBitsUsed, iAvailableBits ) ) + { + iDone++; + } + ELSE IF( EQ_32( iBitsUsed, iAvailableBits ) ) + { + iDone++; + } + + IF( GT_32( iBitsUsed, iAvailableBits ) ) + { + *piAllocOffset -= iDelta; + iDelta = L_shr( iDelta, 1 ); + } + ELSE IF( LT_32( iBitsUsed, iAvailableBits ) ) + { + *piAllocOffset += iDelta; + iDelta = L_shr( iDelta, 1 ); + } + } + } + IF( GT_32( psPredictionEncoder->iNumSubSets, 1 ) ) + { + FOR( n = 0; n < iChannels; n++ ) + { + mvl2l( psPredictionEncoder->ppfPredStateRealTmp_fx[n], psPredictionEncoder->ppfPredStateReal_fx[n], LCLD_BANDS ); + mvl2l( psPredictionEncoder->ppfPredStateImagTmp_fx[n], psPredictionEncoder->ppfPredStateImag_fx[n], LCLD_BANDS ); + } + } + return iBitsUsed; +} +#endif diff --git a/lib_isar/isar_lcld_prot.h b/lib_isar/isar_lcld_prot.h new file mode 100644 index 000000000..a37134857 --- /dev/null +++ b/lib_isar/isar_lcld_prot.h @@ -0,0 +1,457 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_LCLD_PROT_H +#define ISAR_LCLD_PROT_H + +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "typedef.h" +#include "common_api_types.h" +#include "isar_lcld_rom_tables.h" +// #include "prot.h" +/* clang-format off */ + +typedef struct LCLD_ENCODER LCLDEncoder; + +ivas_error CreateLCLDEncoder( + LCLDEncoder **psLCLDEncoder_out, + const Word32 iSampleRate, + const Word32 iChannels, + const Word32 iTargetBitRate, + const Word32 iAllowSidePred, + const Word16 iNumBlocks, + const Word16 iNumSubSets, + const Word32 iRealOnlyOut); +void DeleteLCLDEncoder( + LCLDEncoder *psLCLDEncoder +); + +Word32 EncodeLCLDFrame( + LCLDEncoder *psLCLDEncoder, + Word32 ***pppfLCLDReal_fx, + Word32 ***pppfLCLDImag_fx, + Word32 *piNumiBites, + const Word32 available_bits, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word16 *q_final); + +Word32 GetNumGroups( + LCLDEncoder *psLCLDEncoder +); + + +typedef struct LCLD_DECODER LCLDDecoder; + +ivas_error CreateLCLDDecoder( + LCLDDecoder **psLCLDDecoder_out, + const Word32 iSampleRate, + const Word32 iChannels, + const Word32 iNumBlocks, + const Word32 iRealOnlyOut); + + +void DeleteLCLDDecoder( + LCLDDecoder *psLCLDDecoder +); + +Word32 DecodeLCLDFrame( + LCLDDecoder *psLCLDDecoder, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word32 ***pppfLCLDReal_fx, + Word32 ***pppfLCLDImag_fx, + Word16 Q_in, + Word16 *Q_out +); + +/*----------------------------------------------------------------------------------* + * MSPred prototypes + *----------------------------------------------------------------------------------*/ +Word32 quantPhase_fx( + Word32 phase, + Word16 exp); + +int32_t quantPhase( + float phase +); + +void cplxmult( + float *pr1, + float *pi1, + float r2, + float i2 +); +void cplxmult_fx( + Word32 *pr1, + Word32 *pi1, + Word32 r2, + Word32 i2 +); + +Word32 requantPhase( + Word32 phaseQ +); + +Word32 quantPred_fx( + const Word32 pred, + Word16 exp); +int32_t quantPred( + const float pred +); + +float dequantPhase( + const int32_t phaseQ +); + +float dequantPred( + int32_t predQ +); +Word32 dequantPred_fx( + Word32 predQ +); +Word32 PrepEncode( + Word32 *piQuant, + const Word32 *piMSFlags, + const Word32 numBands +); + +void EncodePhase( + Word32 *phaseQuant, + const Word32 numMSBands, + const Word32 diffDim +); + +void DecodePhase( + Word32 *phaseQuant, + const Word32 numMSBands, + const Word32 diffDim +); + +Word32 EncodePredCoef( + Word32 *predQuant, + const Word32 numMSBands +); + +void DecodePredCoef( + Word32 *phaseQuant, + const Word32 numMSBands +); + +void writeMSPred( + int32_t *phaseQuant, + int32_t *predQuant, + const int32_t MSMode, + const int32_t numMSBands, + int32_t numBands, + void *fid, + int32_t *piMsFlags +); + +Word32 CountMSBits( + Word32 iNumBands, + const Word32 iMSMode, + const Word32 *piMSFlags, + const Word32 *piLRPhaseDiff, + const Word32 *piMSPredCoef +); + + +/*----------------------------------------------------------------------------------* + * NoiseGen prototypes + *----------------------------------------------------------------------------------*/ + +typedef struct NOISE_GEN +{ + int32_t iNoiseBufferLength; + int32_t iNoiseBufferMask; + int32_t iNoiseBufferIndex; + float *pfNoiseBuffer; +} NoiseGen; + +void DeleteNoiseGen( + NoiseGen *psNoiseGen +); + +inline float GetNoise( NoiseGen *psNoiseGen ) +{ + float fNoiseSample; + + fNoiseSample = psNoiseGen->pfNoiseBuffer[psNoiseGen->iNoiseBufferIndex]; + psNoiseGen->iNoiseBufferIndex++; + psNoiseGen->iNoiseBufferIndex &= psNoiseGen->iNoiseBufferMask; + + return fNoiseSample; +} +inline Word32 GetNoise_fx( NoiseGen *psNoiseGen ) +{ + Word32 fNoiseSample; + + fNoiseSample = (Word32) (psNoiseGen->pfNoiseBuffer[psNoiseGen->iNoiseBufferIndex]* (1<<14)); + psNoiseGen->iNoiseBufferIndex++; + psNoiseGen->iNoiseBufferIndex &= psNoiseGen->iNoiseBufferMask; + + return fNoiseSample; +} + +/*----------------------------------------------------------------------------------* + * PereptualModel prototypes + *----------------------------------------------------------------------------------*/ + +extern void PerceptualModel( + const int32_t iMaxQuantBands, + const int32_t *piRMSEnvelope, + int32_t *piExcitation, + int32_t *piSMR +); +extern void PerceptualModel_fx( + const Word32 iMaxQuantBands, + const Word32 *piRMSEnvelope, + Word32 *piExcitation, + Word32 *piSMR +); + +extern void PerceptualModelStereo_fx( + const Word32 iMaxQuantBands, + const Word32 *piMSFlags, + const Word32 *piRMSEnvelope0, + const Word32 *piRMSEnvelope1, + Word32 *piExcitation0, + Word32 *piExcitation1, + Word32 *piSMR0, + Word32 *piSMR1 +); +extern void PerceptualModelStereo( + const int32_t iMaxQuantBands, + const int32_t *piMSFlags, + const int32_t *piRMSEnvelope0, + const int32_t *piRMSEnvelope1, + int32_t *piExcitation0, + int32_t *piExcitation1, + int32_t *piSMR0, + int32_t *piSMR1 +); + + +/*----------------------------------------------------------------------------------* + * PredEncoder/PredDecoder prototypes + *----------------------------------------------------------------------------------*/ + +typedef struct PREDICTION_ENCODER +{ + int32_t iChannels; + int32_t iNumBlocks; + + int32_t iSubSetId; + int32_t iNumSubSets; + int32_t iMaxNumPredBands; + Word32 ***pppfInpBufReal_fx; /* channels, LCLD_PRED_WIN_LEN, bands */ + Word32 ***pppfInpBufImag_fx; + Word32 **ppfPredStateReal_fx; /* channels, bands */ + Word32 **ppfPredStateImag_fx; + Word32 **ppfPredStateRealTmp_fx; + Word32 **ppfPredStateImagTmp_fx; + Word32 **ppfInpPrevReal_fx; /* channels, bands */ + Word32 **ppfInpPrevImag_fx; + float ***pppfInpBufReal; /* channels, LCLD_PRED_WIN_LEN, bands */ + float ***pppfInpBufImag; + float **ppfPredStateReal; /* channels, bands */ + float **ppfPredStateImag; + float **ppfPredStateRealTmp; + float **ppfPredStateImagTmp; + float **ppfInpPrevReal; /* channels, bands */ + float **ppfInpPrevImag; + Word32 pfRxxReal_fx[2]; + Word32 pfRxxImag_fx[2]; + float pfRxxReal[2]; + float pfRxxImag[2]; + + int32_t *piPredChanEnable; + int32_t *piNumPredBands; + int32_t **ppiPredBandEnable; + + Word32 **ppfA1Real_fx; + Word32 **ppfA1Imag_fx; + float **ppfA1Real; + float **ppfA1Imag; + + int32_t **ppiA1Mag; + int32_t **ppiA1Phase; +} PredictionEncoder; + +ivas_error CreatePredictionEncoder_fx( + PredictionEncoder **psPredictionEncoder_out, + const Word32 iChannels, + const Word32 iNumBlocks, + const Word32 iNumSubSets, + const Word32 iMaxNumPredBands ); + +void DeletePredictionEncoder_fx( + PredictionEncoder *psPredictionEncoder ); +ivas_error CreatePredictionEncoder( + PredictionEncoder **psPredictionEncoder_out, + const int32_t iChannels, + const int32_t iNumBlocks, + const int32_t iNumSubSets, + const int32_t iMaxNumPredBands +); + +void DeletePredictionEncoder( + PredictionEncoder *psPredictionEncoder +); + +void ComputePredictors( + PredictionEncoder *psPredictionEncoder, + float ***pppfReal, + float ***pppfImag +); +void ComputePredictors_fx( + PredictionEncoder *psPredictionEncoder, + Word32 ***pppfReal_fx, //Q12? + Word32 ***pppfImag_fx); //Q12? + + +Word32 WritePredictors( + PredictionEncoder *psPredictionEncoder, + ISAR_SPLIT_REND_BITS_HANDLE pBits ); + +typedef struct PREDICTION_DECODER +{ + int32_t iChannels; + int32_t iNumBlocks; + int32_t iSubSetId; + int32_t iNumSubSets; + Word32 **ppfPredStateReal_fx; + Word32 **ppfPredStateImag_fx; + + int32_t *piPredChanEnable; + int32_t **ppiPredBandEnable; + /* PLC_IMPROVEMENT */ + int32_t **ppiDecodingUnresolved; + int32_t **ppiDecodingFailed; + int32_t **ppiDecodingFailedPrev; + Word32 **ppfA1Real_fx; /* Q31 */ + Word32 **ppfA1Imag_fx; /* Q31 */ + + int32_t **ppiA1Mag; + int32_t **ppiA1Phase; + + Word32 pfMagLUT_fx[1 << PRED_QUNAT_FILTER_MAG_BITS]; /* Q31 */ + Word32 pfP2RRealLUT_fx[1 << PRED_QUANT_FILTER_PHASE_BITS]; /* Q31 */ + Word32 pfP2RImagLUT_fx[1 << PRED_QUANT_FILTER_PHASE_BITS]; /* Q31 */ + +} PredictionDecoder; + + +ivas_error CreatePredictionDecoder_fx( + PredictionDecoder **psPredictionDecoder_out, + const Word32 iChannels, + const Word32 iNumBlocks ); + +void DeletePredictionDecoder_fx( + PredictionDecoder *psPredictionDecoder ); + +Word32 ReadPredictors_fx( + PredictionDecoder *psPredictionDecoder, + ISAR_SPLIT_REND_BITS_HANDLE pBits +); + +/* PLC_IMPROVEMENT */ +void UpdatePredictionSubSetId( + PredictionEncoder *psPredictionEncoder); + +void SetDecodingUnresolved( + LCLDDecoder *psLCLDDecoder); + +int32_t AnyDecodingFailedPrev( + LCLDDecoder *psLCLDDecoder); + +int32_t AnyDecodingFailed( + LCLDDecoder *psLCLDDecoder); + +int32_t **GetDecodingFailedStatus( + LCLDDecoder *psLCLDDecoder); + +int16_t GetNumSubSets( + LCLDDecoder *psLCLDDecoder); + +int32_t **GetDecodingFailedPrevStatus( + LCLDDecoder *psLCLDDecoder); + +void SetDecodingPassed( + PredictionDecoder *psPredictionDecoder); + +void UpdateDecodingUnresolved( + PredictionDecoder *psPredictionDecoder); + +void UpdateDecodingFailedStatus( + PredictionDecoder *psPredictionDecoder); + +int32_t AnyDecodingUnresolved( + PredictionDecoder *psPredictionDecoder); + +void ApplyInversePredictors_fx( + PredictionDecoder *psPredictionDecoder, + Word32 ***pppfReal, + Word32 ***pppfImag +); + + +/*----------------------------------------------------------------------------------* + * RMSEnvGrouping prototypes + *----------------------------------------------------------------------------------*/ + +typedef struct RMS_ENVELOPE_GROUPING RMSEnvelopeGrouping; + +RMSEnvelopeGrouping *CreateRMSEnvelopeGrouping( + const int32_t iNumBlocks +); + +void DeleteRMSEnvelopeGrouping( + RMSEnvelopeGrouping *psRMSEnvelopeGrouping +); +void ComputeEnvelopeGrouping( + RMSEnvelopeGrouping *psRMSEnvelopeGrouping, + const int32_t iChannels, + const int32_t iNumBands, + const int32_t *piBandwidths, + Word32 ***pppfReal_fx, + Word32 ***pppfImag_fx, + int32_t *piNumGroups, + int32_t *piGroupLengths, + int32_t ***pppiRMSEnvelope , + Word16 q_final +); + +#endif +/* clang-format on */ + +#endif /* _LCLD_ENCODER_H_ */ diff --git a/lib_isar/isar_lcld_rom_tables.c b/lib_isar/isar_lcld_rom_tables.c new file mode 100644 index 000000000..d101c0eac --- /dev/null +++ b/lib_isar/isar_lcld_rom_tables.c @@ -0,0 +1,21207 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include "isar_lcld_rom_tables.h" +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "wmc_auto.h" +#include "prot.h" +#include "isar_lcld_prot.h" +#include + +/* clang-format off */ +const int32_t c_aiNumLcldBandsPerBand[MAX_BANDS_48] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 21, 24, 27, 31, 37, 43, 50, 60 +}; + +const int32_t c_aiBandIdPerLcldBand[LCLD_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, + 18, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 +}; +/* phi = (-12:12)'/12 *pi; tmp = [cos(phi),sin(phi)]; tmp = tmp';sprintf('{%.8ff, %.8ff},\n',tmp(:)) */ +const float c_afRotRealImag[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] = +{ + { -1.00000000f, -0.00000000f }, + { -0.96592583f, -0.25881905f }, + { -0.86602540f, -0.50000000f }, + { -0.70710678f, -0.70710678f }, + { -0.50000000f, -0.86602540f }, + { -0.25881905f, -0.96592583f }, + { 0.00000000f, -1.00000000f }, + { 0.25881905f, -0.96592583f }, + { 0.50000000f, -0.86602540f }, + { 0.70710678f, -0.70710678f }, + { 0.86602540f, -0.50000000f }, + { 0.96592583f, -0.25881905f }, + { 1.00000000f, 0.00000000f }, + { 0.96592583f, 0.25881905f }, + { 0.86602540f, 0.50000000f }, + { 0.70710678f, 0.70710678f }, + { 0.50000000f, 0.86602540f }, + { 0.25881905f, 0.96592583f }, + { 0.00000000f, 1.00000000f }, + { -0.25881905f, 0.96592583f }, + { -0.50000000f, 0.86602540f }, + { -0.70710678f, 0.70710678f }, + { -0.86602540f, 0.50000000f }, + { -0.96592583f, 0.25881905f }, + { -1.00000000f, 0.00000000f } +}; + +const Word32 c_afRotRealImag_fx[PHASE_MAX_VAL - PHASE_MIN_VAL + 1][2] = /*Q31*/ +{ + {-2147483647,0,}, + {-2074309888,-555809664,}, + {-1859775360,-1073741824,}, + {-1518500224,-1518500224,}, + {-1073741824,-1859775360,}, + {-555809664,-2074309888,}, + {0,-2147483647,}, + {555809664,-2074309888,}, + {1073741824,-1859775360,}, + {1518500224,-1518500224,}, + {1859775360,-1073741824,}, + {2074309888,-555809664,}, + {2147483647,0,}, + {2074309888,555809664,}, + {1859775360,1073741824,}, + {1518500224,1518500224,}, + {1073741824,1859775360,}, + {555809664,2074309888,}, + {0,2147483647,}, + {-555809664,2074309888,}, + {-1073741824,1859775360,}, + {-1518500224,1518500224,}, + {-1859775360,1073741824,}, + {-2074309888,555809664,}, + {-2147483647,0,}, + +}; +/* Move this to perceptual model ? */ +const int32_t c_aiBandwidths48[MAX_BANDS_48] = +{ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 3, + 3, + 4, + 6, + 6, + 7, + 10, +}; + + +const float c_afScaleFactor[ALLOC_TABLE_SIZE] = { + 0.0f, + 0.353553390593f, + 0.420448207627f, + 0.500000000000f, + 0.594603557501f, + 0.707106781187f, + 0.840896415254f, + 1.000000000000f, + 1.189207115003f, + 1.414213562373f, + 1.681792830507f, + 2.000000000000f, + 2.378414230005f, + 2.828427124746f, + 3.363585661015f, + 4.0f, + 4.756828460011f, + 5.656854249492f, + 6.727171322030f, + 8.0f, + 9.513656920022f, + 11.31370849898f, + 13.45434264406f, + 16.00000000000f, + 19.02731384004f, + 22.62741699797f, + 26.90868528812f, + 32.000000000000000f, + 38.054627680087073f, + 45.254833995939038f, + 53.817370576237735f, + 64.000000000000000f, +}; +const Word32 c_afScaleFactor_fx[ALLOC_TABLE_SIZE] = { + //Q24 + 0, + 5931641, + 7053950, + 8388608, + 9975792, + 11863283, + 14107901, + 16777216, + 19951584, + 23726566, + 28215802, + 33554432, + 39903168, + 47453132, + 56431604, + 67108864, + 79806336, + 94906264, + 112863208, + 134217728, + 159612672, + 189812528, + 225726416, + 268435456, + 319225344, + 379625056, + 451452832, + 536870912, + 638450688, + 759250112, + 902905664, + 1073741824, +}; +const float c_afInvScaleFactor[ALLOC_TABLE_SIZE] = { + 0.0f, + 2.367513562373095f, + 2.046407115002721f, + 1.775900000000000f, + 1.536446415253715f, + 1.323056781186548f, + 1.132903557501360f, + 0.965800000000000f, + 0.821348207626857f, + 0.695103390593274f, + 0.587801778750680f, + 0.495800000000000f, + 0.418124103813429f, + 0.352176695296637f, + 0.296200889375340f, + 0.249400000000000f, + 0.209812051906714f, + 0.176538347648318f, + 0.148525444687670f, + 0.124900000000000f, + 0.105056025953357f, + 0.088388347648318f, + 0.074325444687670f, + 0.062500000000000f, + 0.052556025953357f, + 0.044194173824159f, + 0.037162722343835f, + 0.031250000000000f, + 0.026278012976679f, + 0.022097086912080f, + 0.018581361171918f, + 0.015625000000000f, +}; +const Word32 c_afInvScaleFactor_fx[ALLOC_TABLE_SIZE] = { + //Q29 + 0, + 1271049216, + 1098656512, + 953429056, + 824873408, + 710310720, + 608222976, + 518509920, + 440957952, + 373180800, + 315573664, + 266180592, + 224478672, + 189073424, + 159021648, + 133895608, + 112641984, + 94778304, + 79738992, + 67055176, + 56401524, + 47453132, + 39903168, + 33554432, + 28215802, + 23726566, + 19951584, + 16777216, + 14107901, + 11863283, + 9975792, + 8388608, +}; +const float c_afRMSEnvReconstructTable[ENV_RECONSTRUCT_TABLE_SIZE] = { + 2.32830644e-10f, + 3.29272254e-10f, + 4.65661287e-10f, + 6.58544508e-10f, + 9.31322575e-10f, + 1.31708902e-09f, + 1.86264515e-09f, + 2.63417803e-09f, + 3.72529030e-09f, + 5.26835606e-09f, + 7.45058060e-09f, + 1.05367121e-08f, + 1.49011612e-08f, + 2.10734243e-08f, + 2.98023224e-08f, + 4.21468485e-08f, + 5.96046448e-08f, + 8.42936970e-08f, + 1.19209290e-07f, + 1.68587394e-07f, + 2.38418579e-07f, + 3.37174788e-07f, + 4.76837158e-07f, + 6.74349576e-07f, + 9.53674316e-07f, + 1.34869915e-06f, + 1.90734863e-06f, + 2.69739830e-06f, + 3.81469727e-06f, + 5.39479661e-06f, + 7.62939453e-06f, + 1.07895932e-05f, + 1.52587891e-05f, + 2.15791864e-05f, + 3.05175781e-05f, + 4.31583729e-05f, + 6.10351562e-05f, + 8.63167458e-05f, + 1.22070312e-04f, + 1.72633492e-04f, + 2.44140625e-04f, + 3.45266983e-04f, + 4.88281250e-04f, + 6.90533966e-04f, + 9.76562500e-04f, + 1.38106793e-03f, + 1.95312500e-03f, + 2.76213586e-03f, + 3.90625000e-03f, + 5.52427173e-03f, + 7.81250000e-03f, + 1.10485435e-02f, + 1.56250000e-02f, + 2.20970869e-02f, + 3.12500000e-02f, + 4.41941738e-02f, + 6.25000000e-02f, + 8.83883476e-02f, + 1.25000000e-01f, + 1.76776695e-01f, + 2.50000000e-01f, + 3.53553391e-01f, + 5.00000000e-01f, + 7.07106781e-01f, + 1.00000000e+00f, + 1.41421356e+00f, + 2.00000000e+00f, + 2.82842712e+00f, + 4.00000000e+00f, + 5.65685425e+00f, + 8.00000000e+00f, + 1.13137085e+01f, + 1.60000000e+01f, + 2.26274170e+01f, + 3.20000000e+01f, + 4.52548340e+01f, + 6.40000000e+01f, + 9.05096680e+01f, + 1.28000000e+02f, + 1.81019336e+02f, + 2.56000000e+02f, + 3.62038672e+02f, + 5.12000000e+02f, + 7.24077344e+02f, + 1.02400000e+03f, + 1.44815469e+03f, + 2.04800000e+03f, + 2.89630938e+03f, + 4.09600000e+03f, + 5.79261875e+03f, + 8.19200000e+03f, + 1.15852375e+04f, + 1.63840000e+04f, + 2.31704750e+04f, + 3.27680000e+04f, + 4.63409500e+04f, + 6.55360000e+04f, + 9.26819000e+04f, + 1.31072000e+05f, + 1.85363800e+05f, + 2.62144000e+05f, + 3.70727600e+05f, + 5.24288000e+05f, + 7.41455200e+05f, + 1.04857600e+06f, + 1.48291040e+06f, + 2.09715200e+06f, + 2.96582080e+06f, + 4.19430400e+06f, + 5.93164160e+06f, + 8.38860800e+06f, + 1.18632832e+07f, + 1.67772160e+07f, + 2.37265664e+07f, + 3.35544320e+07f, + 4.74531328e+07f, + 6.71088640e+07f, + 9.49062656e+07f, + 1.34217728e+08f, + 1.89812531e+08f, + 2.68435456e+08f, + 3.79625062e+08f, + 5.36870912e+08f, + 7.59250125e+08f, + 1.07374182e+09f, + 1.51850025e+09f, + 2.14748365e+09f, + 3.03700050e+09f, + 4.29496730e+09f, +}; + +const int16_t c_afRMSEnvReconstructTable_exp[ENV_RECONSTRUCT_TABLE_SIZE] = +{ + 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0, 0, -1, -1, -2 +}; +const Word32 c_aiQuantMaxValues_fx[ALLOC_TABLE_SIZE] = { + //Q21 + 0, +6291456, +6291456, +8388608, +10485760, +10485760, +12582912, +14680064, +16777216, +18874368, +25165824, +27262976, +33554432, +35651584, +39845888, +48234496, +54525952, +54525952, +56623104, +58720256, +65011712, +75497472, +79691776, +94371840, +113246208, +134217728, +159383552, +188743680, +226492416, +268435456, +318767104, +377487360, +}; +const int32_t c_aiQuantMaxValues[ALLOC_TABLE_SIZE] = { + 0, + 3, + 3, + 4, + 5, + 5, + 6, + 7, + 8, + 9, + 12, + 13, + 16, + 17, + 19, + 23, + 26, + 26, + 27, + 28, + 31, + 36, + 38, + 45, + 54, + 64, + 76, + 90, + 108, + 128, + 152, + 180, +}; +const Word32 c_aiHuffmanDim_fx[ALLOC_TABLE_SIZE] = { + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +const Word32 c_aiHuffmanMod_fx[ALLOC_TABLE_SIZE] = { + 0, + 4, + 4, + 5, + 6, + 6, + 7, + 8, + 9, + 10, + 13, + 14, + 17, + 18, + 20, + 24, + 27, + 27, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +const int32_t c_aiHuffmanDim[ALLOC_TABLE_SIZE] = { + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; + +const int32_t c_aiHuffmanMod[ALLOC_TABLE_SIZE] = { + 0, + 4, + 4, + 5, + 6, + 6, + 7, + 8, + 9, + 10, + 13, + 14, + 17, + 18, + 20, + 24, + 27, + 27, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, +}; +const int32_t c_aiHuffmanSize[ALLOC_TABLE_SIZE] = { + 1, + 16, + 16, + 25, + 36, + 36, + 49, + 64, + 81, + 100, + 169, + 196, + 289, + 324, + 400, + 576, + 729, + 729, + 28, + 29, + 32, + 37, + 39, + 46, + 55, + 65, + 77, + 91, + 109, + 129, + 153, + 181, +}; + +const uint32_t c_aaiRMSEnvHuffEnc[64][2] = { + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0012, 0x000b }, + { 0x000d, 0x0002 }, + { 0x000e, 0x0001 }, + { 0x000e, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x000b, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0007, 0x0004 }, + { 0x0006, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0005, 0x0003 }, + { 0x0004, 0x0002 }, + { 0x0003, 0x0002 }, + { 0x0002, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0004, 0x0003 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0007 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000e, 0x0003 }, + { 0x0010, 0x0003 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, +}; + +const uint32_t c_aaiRMSEnvHuffDec[13][HUFF_DEC_TABLE_SIZE] = { + { + 0x0002ffff, + 0x0001ffff, + 0x0000001d, + 0x00000022, + 0x0001001e, + 0x0001001e, + 0x00010021, + 0x00010021, + 0x0002001f, + 0x0002001f, + 0x0002001f, + 0x0002001f, + 0x00020020, + 0x00020020, + 0x00020020, + 0x00020020, + }, + { + 0x0002001b, + 0x0002001b, + 0x0002001b, + 0x0002001b, + 0x00020023, + 0x00020023, + 0x00020023, + 0x00020023, + 0x0003001c, + 0x0003001c, + 0x0003001c, + 0x0003001c, + 0x0003001c, + 0x0003001c, + 0x0003001c, + 0x0003001c, + }, + { + 0x0006ffff, + 0x0007ffff, + 0x0003ffff, + 0x0004ffff, + 0x0005ffff, + 0x00000017, + 0x00000018, + 0x00000025, + 0x00010019, + 0x00010019, + 0x00010024, + 0x00010024, + 0x0002001a, + 0x0002001a, + 0x0002001a, + 0x0002001a, + }, + { + 0x00030014, + 0x00030014, + 0x00030014, + 0x00030014, + 0x00030014, + 0x00030014, + 0x00030014, + 0x00030014, + 0x00030015, + 0x00030015, + 0x00030015, + 0x00030015, + 0x00030015, + 0x00030015, + 0x00030015, + 0x00030015, + }, + { + 0x00030016, + 0x00030016, + 0x00030016, + 0x00030016, + 0x00030016, + 0x00030016, + 0x00030016, + 0x00030016, + 0x00030026, + 0x00030026, + 0x00030026, + 0x00030026, + 0x00030026, + 0x00030026, + 0x00030026, + 0x00030026, + }, + { + 0x00030027, + 0x00030027, + 0x00030027, + 0x00030027, + 0x00030027, + 0x00030027, + 0x00030027, + 0x00030027, + 0x00030028, + 0x00030028, + 0x00030028, + 0x00030028, + 0x00030028, + 0x00030028, + 0x00030028, + 0x00030028, + }, + { + 0x0009ffff, + 0x0008ffff, + 0x0000002c, + 0x0000002d, + 0x00010010, + 0x00010010, + 0x0001002b, + 0x0001002b, + 0x0001002e, + 0x0001002e, + 0x0001002f, + 0x0001002f, + 0x00020011, + 0x00020011, + 0x00020011, + 0x00020011, + }, + { + 0x00020012, + 0x00020012, + 0x00020012, + 0x00020012, + 0x00020013, + 0x00020013, + 0x00020013, + 0x00020013, + 0x00020029, + 0x00020029, + 0x00020029, + 0x00020029, + 0x0002002a, + 0x0002002a, + 0x0002002a, + 0x0002002a, + }, + { + 0x0003000c, + 0x0003000c, + 0x0003000c, + 0x0003000c, + 0x0003000c, + 0x0003000c, + 0x0003000c, + 0x0003000c, + 0x0003000f, + 0x0003000f, + 0x0003000f, + 0x0003000f, + 0x0003000f, + 0x0003000f, + 0x0003000f, + 0x0003000f, + }, + { + 0x000bffff, + 0x000cffff, + 0x000affff, + 0x00000031, + 0x0002000d, + 0x0002000d, + 0x0002000d, + 0x0002000d, + 0x0002000e, + 0x0002000e, + 0x0002000e, + 0x0002000e, + 0x00020030, + 0x00020030, + 0x00020030, + 0x00020030, + }, + { + 0x0001003a, + 0x0001003a, + 0x0001003b, + 0x0001003b, + 0x0001003c, + 0x0001003c, + 0x0001003d, + 0x0001003d, + 0x0001003e, + 0x0001003e, + 0x0001003f, + 0x0001003f, + 0x0002000b, + 0x0002000b, + 0x0002000b, + 0x0002000b, + }, + { + 0x00000000, + 0x00000001, + 0x00000002, + 0x00000003, + 0x00000004, + 0x00000005, + 0x00010006, + 0x00010006, + 0x00010007, + 0x00010007, + 0x00010008, + 0x00010008, + 0x00010009, + 0x00010009, + 0x0001000a, + 0x0001000a, + }, + { + 0x00010032, + 0x00010032, + 0x00010033, + 0x00010033, + 0x00010034, + 0x00010034, + 0x00010035, + 0x00010035, + 0x00010036, + 0x00010036, + 0x00010037, + 0x00010037, + 0x00010038, + 0x00010038, + 0x00010039, + 0x00010039, + }, +}; + +const uint16_t c_aauiLCLDHuffEnc1[16][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0005, 0x0001 }, + { 0x000b, 0x0000 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + }; + +const uint16_t c_aauiLCLDHuffEnc2[16][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0005, 0x0001 }, + { 0x000c, 0x0000 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000b, 0x0003 }, + }; + +const uint16_t c_aauiLCLDHuffEnc3[25][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000d, 0x0000 }, + { 0x000d, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000d, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x0009, 0x0001 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000d, 0x000a }, + { 0x000d, 0x000b }, + { 0x000d, 0x000c }, + { 0x000d, 0x000d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc4[36][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x0010, 0x0000 }, + { 0x0010, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x000e, 0x0006 }, + { 0x0010, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000e, 0x0007 }, + { 0x0010, 0x0006 }, + { 0x0010, 0x0007 }, + { 0x0010, 0x0008 }, + { 0x0010, 0x0009 }, + { 0x0010, 0x000a }, + { 0x0010, 0x000b }, + { 0x0010, 0x000c }, + { 0x0010, 0x000d }, + { 0x0010, 0x000e }, + { 0x0010, 0x000f }, + { 0x0010, 0x0010 }, + { 0x0010, 0x0011 }, + { 0x000f, 0x0009 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + + }; + +const uint16_t c_aauiLCLDHuffEnc5[36][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000f, 0x0003 }, + { 0x0012, 0x0000 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x0011, 0x0008 }, + { 0x0012, 0x0001 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000d, 0x0001 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0011, 0x0009 }, + { 0x0011, 0x000a }, + { 0x0012, 0x0007 }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + { 0x0012, 0x000c }, + { 0x0012, 0x000d }, + { 0x0012, 0x000e }, + { 0x0012, 0x000f }, + { 0x0011, 0x000b }, + + }; + +const uint16_t c_aauiLCLDHuffEnc6[49][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x0010, 0x0003 }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000a, 0x0002 }, + { 0x0010, 0x0004 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x0012, 0x0007 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x000a, 0x0003 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x0011, 0x0004 }, + { 0x0014, 0x0006 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0010, 0x0005 }, + { 0x000f, 0x0003 }, + { 0x0011, 0x0005 }, + { 0x0014, 0x0009 }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0014, 0x000c }, + { 0x0014, 0x000d }, + { 0x0013, 0x000d }, + { 0x0014, 0x000e }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0014, 0x0013 }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc7[64][2] = + { + { 0x0002, 0x0001 }, + { 0x0002, 0x0002 }, + { 0x0005, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000f, 0x0002 }, + { 0x0015, 0x0000 }, + { 0x0015, 0x0001 }, + { 0x0015, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0009, 0x0002 }, + { 0x000f, 0x0003 }, + { 0x0014, 0x0011 }, + { 0x0015, 0x0003 }, + { 0x0015, 0x0004 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0007, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x0010, 0x0002 }, + { 0x0015, 0x0005 }, + { 0x0015, 0x0006 }, + { 0x0015, 0x0007 }, + { 0x000a, 0x0001 }, + { 0x0009, 0x0003 }, + { 0x000c, 0x0001 }, + { 0x000f, 0x0004 }, + { 0x0012, 0x0006 }, + { 0x0015, 0x0008 }, + { 0x0015, 0x0009 }, + { 0x0015, 0x000a }, + { 0x000f, 0x0005 }, + { 0x000e, 0x0003 }, + { 0x0010, 0x0003 }, + { 0x0012, 0x0007 }, + { 0x0014, 0x0012 }, + { 0x0015, 0x000b }, + { 0x0015, 0x000c }, + { 0x0015, 0x000d }, + { 0x0014, 0x0013 }, + { 0x0014, 0x0014 }, + { 0x0013, 0x000b }, + { 0x0014, 0x0015 }, + { 0x0015, 0x000e }, + { 0x0015, 0x000f }, + { 0x0015, 0x0010 }, + { 0x0015, 0x0011 }, + { 0x0015, 0x0012 }, + { 0x0015, 0x0013 }, + { 0x0015, 0x0014 }, + { 0x0015, 0x0015 }, + { 0x0015, 0x0016 }, + { 0x0015, 0x0017 }, + { 0x0015, 0x0018 }, + { 0x0015, 0x0019 }, + { 0x0015, 0x001a }, + { 0x0015, 0x001b }, + { 0x0015, 0x001c }, + { 0x0015, 0x001d }, + { 0x0015, 0x001e }, + { 0x0015, 0x001f }, + { 0x0015, 0x0020 }, + { 0x0015, 0x0021 }, + }; + +const uint16_t c_aauiLCLDHuffEnc8[81][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000f, 0x0002 }, + { 0x0014, 0x0008 }, + { 0x0017, 0x0000 }, + { 0x0017, 0x0001 }, + { 0x0017, 0x0002 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000f, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0015, 0x000d }, + { 0x0017, 0x0003 }, + { 0x0017, 0x0004 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0007, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x0010, 0x0002 }, + { 0x0013, 0x0005 }, + { 0x0017, 0x0005 }, + { 0x0017, 0x0006 }, + { 0x0017, 0x0007 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000b, 0x0001 }, + { 0x000f, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0016, 0x0015 }, + { 0x0017, 0x0008 }, + { 0x0017, 0x0009 }, + { 0x0017, 0x000a }, + { 0x000f, 0x0005 }, + { 0x000e, 0x0003 }, + { 0x0010, 0x0003 }, + { 0x0012, 0x0006 }, + { 0x0014, 0x0009 }, + { 0x0017, 0x000b }, + { 0x0017, 0x000c }, + { 0x0017, 0x000d }, + { 0x0017, 0x000e }, + { 0x0013, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0013, 0x0007 }, + { 0x0015, 0x000e }, + { 0x0017, 0x000f }, + { 0x0017, 0x0010 }, + { 0x0017, 0x0011 }, + { 0x0017, 0x0012 }, + { 0x0017, 0x0013 }, + { 0x0016, 0x0016 }, + { 0x0016, 0x0017 }, + { 0x0015, 0x000f }, + { 0x0016, 0x0018 }, + { 0x0017, 0x0014 }, + { 0x0017, 0x0015 }, + { 0x0017, 0x0016 }, + { 0x0017, 0x0017 }, + { 0x0017, 0x0018 }, + { 0x0017, 0x0019 }, + { 0x0017, 0x001a }, + { 0x0017, 0x001b }, + { 0x0017, 0x001c }, + { 0x0017, 0x001d }, + { 0x0017, 0x001e }, + { 0x0017, 0x001f }, + { 0x0017, 0x0020 }, + { 0x0017, 0x0021 }, + { 0x0017, 0x0022 }, + { 0x0017, 0x0023 }, + { 0x0017, 0x0024 }, + { 0x0017, 0x0025 }, + { 0x0017, 0x0026 }, + { 0x0017, 0x0027 }, + { 0x0017, 0x0028 }, + { 0x0017, 0x0029 }, + { 0x0016, 0x0019 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc9[100][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000d, 0x0002 }, + { 0x0011, 0x0004 }, + { 0x0014, 0x000a }, + { 0x0017, 0x0000 }, + { 0x0017, 0x0001 }, + { 0x0017, 0x0002 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0009, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x0010, 0x0004 }, + { 0x0013, 0x0007 }, + { 0x0016, 0x0018 }, + { 0x0017, 0x0003 }, + { 0x0017, 0x0004 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0008, 0x0002 }, + { 0x000b, 0x0002 }, + { 0x000e, 0x0002 }, + { 0x0011, 0x0005 }, + { 0x0014, 0x000b }, + { 0x0016, 0x0019 }, + { 0x0017, 0x0005 }, + { 0x0017, 0x0006 }, + { 0x0009, 0x0003 }, + { 0x0008, 0x0003 }, + { 0x000b, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0015, 0x000f }, + { 0x0017, 0x0007 }, + { 0x0017, 0x0008 }, + { 0x0017, 0x0009 }, + { 0x000d, 0x0005 }, + { 0x000c, 0x0003 }, + { 0x000e, 0x0003 }, + { 0x0010, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0014, 0x000c }, + { 0x0017, 0x000a }, + { 0x0016, 0x001a }, + { 0x0017, 0x000b }, + { 0x0017, 0x000c }, + { 0x0011, 0x0006 }, + { 0x0010, 0x0007 }, + { 0x0011, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0015, 0x0010 }, + { 0x0017, 0x000d }, + { 0x0017, 0x000e }, + { 0x0017, 0x000f }, + { 0x0017, 0x0010 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0014, 0x000d }, + { 0x0015, 0x0011 }, + { 0x0017, 0x0011 }, + { 0x0016, 0x001b }, + { 0x0017, 0x0012 }, + { 0x0017, 0x0013 }, + { 0x0017, 0x0014 }, + { 0x0017, 0x0015 }, + { 0x0017, 0x0016 }, + { 0x0015, 0x0012 }, + { 0x0015, 0x0013 }, + { 0x0017, 0x0017 }, + { 0x0016, 0x001c }, + { 0x0017, 0x0018 }, + { 0x0017, 0x0019 }, + { 0x0017, 0x001a }, + { 0x0017, 0x001b }, + { 0x0017, 0x001c }, + { 0x0017, 0x001d }, + { 0x0017, 0x001e }, + { 0x0017, 0x001f }, + { 0x0017, 0x0020 }, + { 0x0017, 0x0021 }, + { 0x0017, 0x0022 }, + { 0x0017, 0x0023 }, + { 0x0017, 0x0024 }, + { 0x0017, 0x0025 }, + { 0x0017, 0x0026 }, + { 0x0017, 0x0027 }, + { 0x0017, 0x0028 }, + { 0x0017, 0x0029 }, + { 0x0017, 0x002a }, + { 0x0017, 0x002b }, + { 0x0017, 0x002c }, + { 0x0017, 0x002d }, + { 0x0017, 0x002e }, + { 0x0017, 0x002f }, + { 0x0016, 0x001d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc10[169][2] = + { + { 0x0001, 0x0001 }, + { 0x0004, 0x0002 }, + { 0x0005, 0x0002 }, + { 0x0007, 0x0002 }, + { 0x000a, 0x0002 }, + { 0x000e, 0x0004 }, + { 0x0011, 0x0007 }, + { 0x0013, 0x0012 }, + { 0x0016, 0x0000 }, + { 0x0016, 0x0001 }, + { 0x0016, 0x0002 }, + { 0x0016, 0x0003 }, + { 0x0016, 0x0004 }, + { 0x0004, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0004, 0x0004 }, + { 0x0007, 0x0003 }, + { 0x000a, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x0010, 0x0007 }, + { 0x0013, 0x0013 }, + { 0x0015, 0x0035 }, + { 0x0016, 0x0005 }, + { 0x0016, 0x0006 }, + { 0x0016, 0x0007 }, + { 0x0016, 0x0008 }, + { 0x0005, 0x0003 }, + { 0x0004, 0x0005 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0002 }, + { 0x000b, 0x0002 }, + { 0x000e, 0x0005 }, + { 0x0010, 0x0008 }, + { 0x0013, 0x0014 }, + { 0x0014, 0x001d }, + { 0x0016, 0x0009 }, + { 0x0016, 0x000a }, + { 0x0016, 0x000b }, + { 0x0016, 0x000c }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000f, 0x0005 }, + { 0x0011, 0x0008 }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0016, 0x000d }, + { 0x0016, 0x000e }, + { 0x0016, 0x000f }, + { 0x0016, 0x0010 }, + { 0x000a, 0x0005 }, + { 0x0009, 0x0003 }, + { 0x000b, 0x0003 }, + { 0x000d, 0x0006 }, + { 0x000f, 0x0006 }, + { 0x0011, 0x0009 }, + { 0x0013, 0x0015 }, + { 0x0014, 0x0020 }, + { 0x0016, 0x0011 }, + { 0x0016, 0x0012 }, + { 0x0016, 0x0013 }, + { 0x0016, 0x0014 }, + { 0x0016, 0x0015 }, + { 0x000e, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0007 }, + { 0x000f, 0x0007 }, + { 0x0011, 0x000a }, + { 0x0012, 0x000c }, + { 0x0016, 0x0016 }, + { 0x0016, 0x0017 }, + { 0x0016, 0x0018 }, + { 0x0016, 0x0019 }, + { 0x0016, 0x001a }, + { 0x0016, 0x001b }, + { 0x0016, 0x001c }, + { 0x0011, 0x000b }, + { 0x0010, 0x0009 }, + { 0x0011, 0x000c }, + { 0x0011, 0x000d }, + { 0x0013, 0x0016 }, + { 0x0016, 0x001d }, + { 0x0016, 0x001e }, + { 0x0016, 0x001f }, + { 0x0016, 0x0020 }, + { 0x0016, 0x0021 }, + { 0x0016, 0x0022 }, + { 0x0016, 0x0023 }, + { 0x0016, 0x0024 }, + { 0x0014, 0x0021 }, + { 0x0014, 0x0022 }, + { 0x0012, 0x000d }, + { 0x0013, 0x0017 }, + { 0x0016, 0x0025 }, + { 0x0016, 0x0026 }, + { 0x0016, 0x0027 }, + { 0x0016, 0x0028 }, + { 0x0016, 0x0029 }, + { 0x0016, 0x002a }, + { 0x0016, 0x002b }, + { 0x0016, 0x002c }, + { 0x0016, 0x002d }, + { 0x0015, 0x0036 }, + { 0x0015, 0x0037 }, + { 0x0014, 0x0023 }, + { 0x0015, 0x0038 }, + { 0x0016, 0x002e }, + { 0x0016, 0x002f }, + { 0x0016, 0x0030 }, + { 0x0016, 0x0031 }, + { 0x0016, 0x0032 }, + { 0x0016, 0x0033 }, + { 0x0016, 0x0034 }, + { 0x0016, 0x0035 }, + { 0x0016, 0x0036 }, + { 0x0016, 0x0037 }, + { 0x0016, 0x0038 }, + { 0x0016, 0x0039 }, + { 0x0016, 0x003a }, + { 0x0016, 0x003b }, + { 0x0016, 0x003c }, + { 0x0016, 0x003d }, + { 0x0016, 0x003e }, + { 0x0016, 0x003f }, + { 0x0016, 0x0040 }, + { 0x0016, 0x0041 }, + { 0x0016, 0x0042 }, + { 0x0016, 0x0043 }, + { 0x0016, 0x0044 }, + { 0x0016, 0x0045 }, + { 0x0016, 0x0046 }, + { 0x0016, 0x0047 }, + { 0x0016, 0x0048 }, + { 0x0016, 0x0049 }, + { 0x0016, 0x004a }, + { 0x0016, 0x004b }, + { 0x0016, 0x004c }, + { 0x0016, 0x004d }, + { 0x0016, 0x004e }, + { 0x0016, 0x004f }, + { 0x0016, 0x0050 }, + { 0x0016, 0x0051 }, + { 0x0016, 0x0052 }, + { 0x0016, 0x0053 }, + { 0x0016, 0x0054 }, + { 0x0016, 0x0055 }, + { 0x0016, 0x0056 }, + { 0x0016, 0x0057 }, + { 0x0016, 0x0058 }, + { 0x0016, 0x0059 }, + { 0x0016, 0x005a }, + { 0x0016, 0x005b }, + { 0x0016, 0x005c }, + { 0x0016, 0x005d }, + { 0x0016, 0x005e }, + { 0x0016, 0x005f }, + { 0x0016, 0x0060 }, + { 0x0016, 0x0061 }, + { 0x0016, 0x0062 }, + { 0x0016, 0x0063 }, + { 0x0016, 0x0064 }, + { 0x0016, 0x0065 }, + { 0x0016, 0x0066 }, + { 0x0016, 0x0067 }, + { 0x0016, 0x0068 }, + { 0x0016, 0x0069 }, + { 0x0015, 0x0039 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc11[196][2] = + { + { 0x0001, 0x0001 }, + { 0x0004, 0x0003 }, + { 0x0005, 0x0003 }, + { 0x0007, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x0012, 0x000d }, + { 0x0014, 0x001f }, + { 0x0016, 0x0000 }, + { 0x0016, 0x0001 }, + { 0x0016, 0x0002 }, + { 0x0016, 0x0003 }, + { 0x0016, 0x0004 }, + { 0x0004, 0x0004 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0006, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x000b, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x0010, 0x0007 }, + { 0x0012, 0x000e }, + { 0x0014, 0x0020 }, + { 0x0016, 0x0005 }, + { 0x0016, 0x0006 }, + { 0x0016, 0x0007 }, + { 0x0016, 0x0008 }, + { 0x0005, 0x0005 }, + { 0x0004, 0x0005 }, + { 0x0006, 0x0004 }, + { 0x0007, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000e, 0x0006 }, + { 0x0011, 0x000a }, + { 0x0012, 0x000f }, + { 0x0015, 0x003b }, + { 0x0016, 0x0009 }, + { 0x0016, 0x000a }, + { 0x0016, 0x000b }, + { 0x0016, 0x000c }, + { 0x0007, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0005 }, + { 0x0009, 0x0005 }, + { 0x000b, 0x0005 }, + { 0x000d, 0x0005 }, + { 0x000f, 0x0006 }, + { 0x0012, 0x0010 }, + { 0x0014, 0x0021 }, + { 0x0016, 0x000d }, + { 0x0016, 0x000e }, + { 0x0016, 0x000f }, + { 0x0016, 0x0010 }, + { 0x0016, 0x0011 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x000a, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000d, 0x0006 }, + { 0x000f, 0x0007 }, + { 0x0011, 0x000b }, + { 0x0013, 0x0017 }, + { 0x0014, 0x0022 }, + { 0x0016, 0x0012 }, + { 0x0016, 0x0013 }, + { 0x0016, 0x0014 }, + { 0x0016, 0x0015 }, + { 0x0016, 0x0016 }, + { 0x000c, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0007 }, + { 0x0010, 0x0008 }, + { 0x0012, 0x0011 }, + { 0x0014, 0x0023 }, + { 0x0015, 0x003c }, + { 0x0016, 0x0017 }, + { 0x0016, 0x0018 }, + { 0x0016, 0x0019 }, + { 0x0016, 0x001a }, + { 0x0016, 0x001b }, + { 0x000f, 0x0008 }, + { 0x000e, 0x0008 }, + { 0x000e, 0x0009 }, + { 0x000f, 0x0009 }, + { 0x0011, 0x000c }, + { 0x0013, 0x0018 }, + { 0x0014, 0x0024 }, + { 0x0016, 0x001c }, + { 0x0016, 0x001d }, + { 0x0016, 0x001e }, + { 0x0016, 0x001f }, + { 0x0016, 0x0020 }, + { 0x0016, 0x0021 }, + { 0x0016, 0x0022 }, + { 0x0011, 0x000d }, + { 0x0010, 0x0009 }, + { 0x0012, 0x0012 }, + { 0x0012, 0x0013 }, + { 0x0014, 0x0025 }, + { 0x0015, 0x003d }, + { 0x0014, 0x0026 }, + { 0x0016, 0x0023 }, + { 0x0016, 0x0024 }, + { 0x0016, 0x0025 }, + { 0x0016, 0x0026 }, + { 0x0016, 0x0027 }, + { 0x0016, 0x0028 }, + { 0x0016, 0x0029 }, + { 0x0014, 0x0027 }, + { 0x0013, 0x0019 }, + { 0x0014, 0x0028 }, + { 0x0014, 0x0029 }, + { 0x0014, 0x002a }, + { 0x0016, 0x002a }, + { 0x0016, 0x002b }, + { 0x0016, 0x002c }, + { 0x0016, 0x002d }, + { 0x0016, 0x002e }, + { 0x0016, 0x002f }, + { 0x0016, 0x0030 }, + { 0x0016, 0x0031 }, + { 0x0016, 0x0032 }, + { 0x0014, 0x002b }, + { 0x0014, 0x002c }, + { 0x0014, 0x002d }, + { 0x0016, 0x0033 }, + { 0x0016, 0x0034 }, + { 0x0016, 0x0035 }, + { 0x0016, 0x0036 }, + { 0x0016, 0x0037 }, + { 0x0016, 0x0038 }, + { 0x0016, 0x0039 }, + { 0x0016, 0x003a }, + { 0x0016, 0x003b }, + { 0x0016, 0x003c }, + { 0x0016, 0x003d }, + { 0x0016, 0x003e }, + { 0x0016, 0x003f }, + { 0x0016, 0x0040 }, + { 0x0016, 0x0041 }, + { 0x0016, 0x0042 }, + { 0x0016, 0x0043 }, + { 0x0016, 0x0044 }, + { 0x0016, 0x0045 }, + { 0x0016, 0x0046 }, + { 0x0016, 0x0047 }, + { 0x0016, 0x0048 }, + { 0x0016, 0x0049 }, + { 0x0016, 0x004a }, + { 0x0016, 0x004b }, + { 0x0016, 0x004c }, + { 0x0016, 0x004d }, + { 0x0016, 0x004e }, + { 0x0016, 0x004f }, + { 0x0016, 0x0050 }, + { 0x0016, 0x0051 }, + { 0x0016, 0x0052 }, + { 0x0016, 0x0053 }, + { 0x0016, 0x0054 }, + { 0x0016, 0x0055 }, + { 0x0016, 0x0056 }, + { 0x0016, 0x0057 }, + { 0x0016, 0x0058 }, + { 0x0016, 0x0059 }, + { 0x0016, 0x005a }, + { 0x0016, 0x005b }, + { 0x0016, 0x005c }, + { 0x0016, 0x005d }, + { 0x0016, 0x005e }, + { 0x0016, 0x005f }, + { 0x0016, 0x0060 }, + { 0x0016, 0x0061 }, + { 0x0016, 0x0062 }, + { 0x0016, 0x0063 }, + { 0x0016, 0x0064 }, + { 0x0016, 0x0065 }, + { 0x0016, 0x0066 }, + { 0x0016, 0x0067 }, + { 0x0016, 0x0068 }, + { 0x0016, 0x0069 }, + { 0x0016, 0x006a }, + { 0x0016, 0x006b }, + { 0x0016, 0x006c }, + { 0x0016, 0x006d }, + { 0x0016, 0x006e }, + { 0x0016, 0x006f }, + { 0x0016, 0x0070 }, + { 0x0016, 0x0071 }, + { 0x0016, 0x0072 }, + { 0x0016, 0x0073 }, + { 0x0016, 0x0074 }, + { 0x0016, 0x0075 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc12[289][2] = + { + { 0x0001, 0x0001 }, + { 0x0004, 0x0004 }, + { 0x0005, 0x0004 }, + { 0x0007, 0x0004 }, + { 0x0008, 0x0002 }, + { 0x000b, 0x0004 }, + { 0x000e, 0x0006 }, + { 0x0010, 0x0009 }, + { 0x0012, 0x0014 }, + { 0x0013, 0x001f }, + { 0x0016, 0x0000 }, + { 0x0016, 0x0001 }, + { 0x0016, 0x0002 }, + { 0x0016, 0x0003 }, + { 0x0016, 0x0004 }, + { 0x0016, 0x0005 }, + { 0x0016, 0x0006 }, + { 0x0004, 0x0005 }, + { 0x0004, 0x0006 }, + { 0x0005, 0x0005 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000d, 0x0006 }, + { 0x000f, 0x0008 }, + { 0x0011, 0x000c }, + { 0x0013, 0x0020 }, + { 0x0016, 0x0007 }, + { 0x0015, 0x0063 }, + { 0x0016, 0x0008 }, + { 0x0016, 0x0009 }, + { 0x0016, 0x000a }, + { 0x0016, 0x000b }, + { 0x0016, 0x000c }, + { 0x0005, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0005, 0x0007 }, + { 0x0006, 0x0004 }, + { 0x0008, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000d, 0x0007 }, + { 0x0010, 0x000a }, + { 0x0012, 0x0015 }, + { 0x0015, 0x0064 }, + { 0x0016, 0x000d }, + { 0x0016, 0x000e }, + { 0x0016, 0x000f }, + { 0x0016, 0x0010 }, + { 0x0016, 0x0011 }, + { 0x0016, 0x0012 }, + { 0x0016, 0x0013 }, + { 0x0006, 0x0005 }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0008, 0x0005 }, + { 0x000a, 0x0005 }, + { 0x000c, 0x0005 }, + { 0x000e, 0x0007 }, + { 0x0010, 0x000b }, + { 0x0012, 0x0016 }, + { 0x0014, 0x0037 }, + { 0x0015, 0x0065 }, + { 0x0016, 0x0014 }, + { 0x0016, 0x0015 }, + { 0x0016, 0x0016 }, + { 0x0016, 0x0017 }, + { 0x0016, 0x0018 }, + { 0x0016, 0x0019 }, + { 0x0008, 0x0006 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0007 }, + { 0x000a, 0x0006 }, + { 0x000c, 0x0006 }, + { 0x000e, 0x0008 }, + { 0x0010, 0x000c }, + { 0x0011, 0x000d }, + { 0x0013, 0x0021 }, + { 0x0015, 0x0066 }, + { 0x0016, 0x001a }, + { 0x0016, 0x001b }, + { 0x0016, 0x001c }, + { 0x0016, 0x001d }, + { 0x0016, 0x001e }, + { 0x0016, 0x001f }, + { 0x0016, 0x0020 }, + { 0x000b, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0007 }, + { 0x000e, 0x0009 }, + { 0x000f, 0x0009 }, + { 0x0011, 0x000e }, + { 0x0013, 0x0022 }, + { 0x0015, 0x0067 }, + { 0x0015, 0x0068 }, + { 0x0016, 0x0021 }, + { 0x0016, 0x0022 }, + { 0x0016, 0x0023 }, + { 0x0016, 0x0024 }, + { 0x0016, 0x0025 }, + { 0x0016, 0x0026 }, + { 0x0016, 0x0027 }, + { 0x000e, 0x000a }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000e, 0x000b }, + { 0x000f, 0x000a }, + { 0x0011, 0x000f }, + { 0x0013, 0x0023 }, + { 0x0014, 0x0038 }, + { 0x0016, 0x0028 }, + { 0x0016, 0x0029 }, + { 0x0016, 0x002a }, + { 0x0016, 0x002b }, + { 0x0016, 0x002c }, + { 0x0016, 0x002d }, + { 0x0016, 0x002e }, + { 0x0016, 0x002f }, + { 0x0016, 0x0030 }, + { 0x0010, 0x000d }, + { 0x000f, 0x000b }, + { 0x0010, 0x000e }, + { 0x0010, 0x000f }, + { 0x0012, 0x0017 }, + { 0x0013, 0x0024 }, + { 0x0014, 0x0039 }, + { 0x0016, 0x0031 }, + { 0x0016, 0x0032 }, + { 0x0016, 0x0033 }, + { 0x0016, 0x0034 }, + { 0x0016, 0x0035 }, + { 0x0016, 0x0036 }, + { 0x0016, 0x0037 }, + { 0x0016, 0x0038 }, + { 0x0016, 0x0039 }, + { 0x0016, 0x003a }, + { 0x0013, 0x0025 }, + { 0x0011, 0x0010 }, + { 0x0011, 0x0011 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0014, 0x003a }, + { 0x0014, 0x003b }, + { 0x0016, 0x003b }, + { 0x0016, 0x003c }, + { 0x0016, 0x003d }, + { 0x0016, 0x003e }, + { 0x0016, 0x003f }, + { 0x0016, 0x0040 }, + { 0x0016, 0x0041 }, + { 0x0016, 0x0042 }, + { 0x0016, 0x0043 }, + { 0x0016, 0x0044 }, + { 0x0015, 0x0069 }, + { 0x0014, 0x003c }, + { 0x0014, 0x003d }, + { 0x0015, 0x006a }, + { 0x0015, 0x006b }, + { 0x0015, 0x006c }, + { 0x0016, 0x0045 }, + { 0x0016, 0x0046 }, + { 0x0016, 0x0047 }, + { 0x0016, 0x0048 }, + { 0x0016, 0x0049 }, + { 0x0016, 0x004a }, + { 0x0016, 0x004b }, + { 0x0016, 0x004c }, + { 0x0016, 0x004d }, + { 0x0016, 0x004e }, + { 0x0016, 0x004f }, + { 0x0016, 0x0050 }, + { 0x0016, 0x0051 }, + { 0x0015, 0x006d }, + { 0x0016, 0x0052 }, + { 0x0016, 0x0053 }, + { 0x0016, 0x0054 }, + { 0x0016, 0x0055 }, + { 0x0016, 0x0056 }, + { 0x0016, 0x0057 }, + { 0x0016, 0x0058 }, + { 0x0016, 0x0059 }, + { 0x0016, 0x005a }, + { 0x0016, 0x005b }, + { 0x0016, 0x005c }, + { 0x0016, 0x005d }, + { 0x0016, 0x005e }, + { 0x0016, 0x005f }, + { 0x0016, 0x0060 }, + { 0x0016, 0x0061 }, + { 0x0016, 0x0062 }, + { 0x0016, 0x0063 }, + { 0x0016, 0x0064 }, + { 0x0016, 0x0065 }, + { 0x0016, 0x0066 }, + { 0x0016, 0x0067 }, + { 0x0016, 0x0068 }, + { 0x0016, 0x0069 }, + { 0x0016, 0x006a }, + { 0x0016, 0x006b }, + { 0x0016, 0x006c }, + { 0x0016, 0x006d }, + { 0x0016, 0x006e }, + { 0x0016, 0x006f }, + { 0x0016, 0x0070 }, + { 0x0016, 0x0071 }, + { 0x0016, 0x0072 }, + { 0x0016, 0x0073 }, + { 0x0016, 0x0074 }, + { 0x0016, 0x0075 }, + { 0x0016, 0x0076 }, + { 0x0016, 0x0077 }, + { 0x0016, 0x0078 }, + { 0x0016, 0x0079 }, + { 0x0016, 0x007a }, + { 0x0016, 0x007b }, + { 0x0016, 0x007c }, + { 0x0016, 0x007d }, + { 0x0016, 0x007e }, + { 0x0016, 0x007f }, + { 0x0016, 0x0080 }, + { 0x0016, 0x0081 }, + { 0x0016, 0x0082 }, + { 0x0016, 0x0083 }, + { 0x0016, 0x0084 }, + { 0x0016, 0x0085 }, + { 0x0016, 0x0086 }, + { 0x0016, 0x0087 }, + { 0x0016, 0x0088 }, + { 0x0016, 0x0089 }, + { 0x0016, 0x008a }, + { 0x0016, 0x008b }, + { 0x0016, 0x008c }, + { 0x0016, 0x008d }, + { 0x0016, 0x008e }, + { 0x0016, 0x008f }, + { 0x0016, 0x0090 }, + { 0x0016, 0x0091 }, + { 0x0016, 0x0092 }, + { 0x0016, 0x0093 }, + { 0x0016, 0x0094 }, + { 0x0016, 0x0095 }, + { 0x0016, 0x0096 }, + { 0x0016, 0x0097 }, + { 0x0016, 0x0098 }, + { 0x0016, 0x0099 }, + { 0x0016, 0x009a }, + { 0x0016, 0x009b }, + { 0x0016, 0x009c }, + { 0x0016, 0x009d }, + { 0x0016, 0x009e }, + { 0x0016, 0x009f }, + { 0x0016, 0x00a0 }, + { 0x0016, 0x00a1 }, + { 0x0016, 0x00a2 }, + { 0x0016, 0x00a3 }, + { 0x0016, 0x00a4 }, + { 0x0016, 0x00a5 }, + { 0x0016, 0x00a6 }, + { 0x0016, 0x00a7 }, + { 0x0016, 0x00a8 }, + { 0x0016, 0x00a9 }, + { 0x0016, 0x00aa }, + { 0x0016, 0x00ab }, + { 0x0016, 0x00ac }, + { 0x0016, 0x00ad }, + { 0x0016, 0x00ae }, + { 0x0016, 0x00af }, + { 0x0016, 0x00b0 }, + { 0x0016, 0x00b1 }, + { 0x0016, 0x00b2 }, + { 0x0016, 0x00b3 }, + { 0x0016, 0x00b4 }, + { 0x0016, 0x00b5 }, + { 0x0016, 0x00b6 }, + { 0x0016, 0x00b7 }, + { 0x0016, 0x00b8 }, + { 0x0016, 0x00b9 }, + { 0x0016, 0x00ba }, + { 0x0016, 0x00bb }, + { 0x0016, 0x00bc }, + { 0x0016, 0x00bd }, + { 0x0016, 0x00be }, + { 0x0016, 0x00bf }, + { 0x0016, 0x00c0 }, + { 0x0016, 0x00c1 }, + { 0x0016, 0x00c2 }, + { 0x0016, 0x00c3 }, + { 0x0016, 0x00c4 }, + { 0x0016, 0x00c5 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc13[324][2] = + { + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0006, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x000a, 0x0005 }, + { 0x000c, 0x0007 }, + { 0x000e, 0x000b }, + { 0x0010, 0x0011 }, + { 0x0012, 0x002d }, + { 0x0015, 0x0000 }, + { 0x0014, 0x0035 }, + { 0x0015, 0x0001 }, + { 0x0015, 0x0002 }, + { 0x0015, 0x0003 }, + { 0x0015, 0x0004 }, + { 0x0015, 0x0005 }, + { 0x0004, 0x0008 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0009 }, + { 0x0004, 0x000a }, + { 0x0006, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0009, 0x0006 }, + { 0x000c, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x0010, 0x0012 }, + { 0x0011, 0x001a }, + { 0x0015, 0x0006 }, + { 0x0015, 0x0007 }, + { 0x0015, 0x0008 }, + { 0x0015, 0x0009 }, + { 0x0015, 0x000a }, + { 0x0015, 0x000b }, + { 0x0015, 0x000c }, + { 0x0005, 0x0007 }, + { 0x0004, 0x000b }, + { 0x0004, 0x000c }, + { 0x0005, 0x0008 }, + { 0x0006, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x000a, 0x0006 }, + { 0x000c, 0x0009 }, + { 0x000e, 0x000c }, + { 0x0010, 0x0013 }, + { 0x0012, 0x002e }, + { 0x0015, 0x000d }, + { 0x0015, 0x000e }, + { 0x0015, 0x000f }, + { 0x0015, 0x0010 }, + { 0x0015, 0x0011 }, + { 0x0015, 0x0012 }, + { 0x0015, 0x0013 }, + { 0x0005, 0x0009 }, + { 0x0004, 0x000d }, + { 0x0005, 0x000a }, + { 0x0006, 0x0007 }, + { 0x0007, 0x0005 }, + { 0x0009, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000d, 0x000a }, + { 0x000f, 0x000e }, + { 0x0010, 0x0014 }, + { 0x0011, 0x001b }, + { 0x0014, 0x0036 }, + { 0x0015, 0x0014 }, + { 0x0015, 0x0015 }, + { 0x0015, 0x0016 }, + { 0x0015, 0x0017 }, + { 0x0015, 0x0018 }, + { 0x0015, 0x0019 }, + { 0x0006, 0x0008 }, + { 0x0005, 0x000b }, + { 0x0006, 0x0009 }, + { 0x0007, 0x0006 }, + { 0x0009, 0x0008 }, + { 0x000a, 0x0007 }, + { 0x000c, 0x000a }, + { 0x000e, 0x000d }, + { 0x0010, 0x0015 }, + { 0x0011, 0x001c }, + { 0x0013, 0x0053 }, + { 0x0015, 0x001a }, + { 0x0015, 0x001b }, + { 0x0015, 0x001c }, + { 0x0015, 0x001d }, + { 0x0015, 0x001e }, + { 0x0015, 0x001f }, + { 0x0015, 0x0020 }, + { 0x0008, 0x0008 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0009 }, + { 0x0009, 0x0009 }, + { 0x000a, 0x0008 }, + { 0x000c, 0x000b }, + { 0x000d, 0x000b }, + { 0x000f, 0x000f }, + { 0x0010, 0x0016 }, + { 0x0011, 0x001d }, + { 0x0014, 0x0037 }, + { 0x0015, 0x0021 }, + { 0x0015, 0x0022 }, + { 0x0015, 0x0023 }, + { 0x0015, 0x0024 }, + { 0x0015, 0x0025 }, + { 0x0015, 0x0026 }, + { 0x0015, 0x0027 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000b, 0x0009 }, + { 0x000c, 0x000c }, + { 0x000d, 0x000c }, + { 0x000f, 0x0010 }, + { 0x0010, 0x0017 }, + { 0x0012, 0x002f }, + { 0x0015, 0x0028 }, + { 0x0015, 0x0029 }, + { 0x0015, 0x002a }, + { 0x0015, 0x002b }, + { 0x0015, 0x002c }, + { 0x0015, 0x002d }, + { 0x0015, 0x002e }, + { 0x0015, 0x002f }, + { 0x0015, 0x0030 }, + { 0x000c, 0x000d }, + { 0x000c, 0x000e }, + { 0x000c, 0x000f }, + { 0x000d, 0x000d }, + { 0x000e, 0x000e }, + { 0x000f, 0x0011 }, + { 0x0010, 0x0018 }, + { 0x0011, 0x001e }, + { 0x0014, 0x0038 }, + { 0x0015, 0x0031 }, + { 0x0015, 0x0032 }, + { 0x0015, 0x0033 }, + { 0x0015, 0x0034 }, + { 0x0015, 0x0035 }, + { 0x0015, 0x0036 }, + { 0x0015, 0x0037 }, + { 0x0015, 0x0038 }, + { 0x0015, 0x0039 }, + { 0x000f, 0x0012 }, + { 0x000e, 0x000f }, + { 0x000e, 0x0010 }, + { 0x000e, 0x0011 }, + { 0x000f, 0x0013 }, + { 0x0010, 0x0019 }, + { 0x0011, 0x001f }, + { 0x0013, 0x0054 }, + { 0x0015, 0x003a }, + { 0x0014, 0x0039 }, + { 0x0015, 0x003b }, + { 0x0015, 0x003c }, + { 0x0015, 0x003d }, + { 0x0015, 0x003e }, + { 0x0015, 0x003f }, + { 0x0015, 0x0040 }, + { 0x0015, 0x0041 }, + { 0x0015, 0x0042 }, + { 0x0010, 0x001a }, + { 0x000f, 0x0014 }, + { 0x000f, 0x0015 }, + { 0x0010, 0x001b }, + { 0x0011, 0x0020 }, + { 0x0012, 0x0030 }, + { 0x0013, 0x0055 }, + { 0x0015, 0x0043 }, + { 0x0015, 0x0044 }, + { 0x0014, 0x003a }, + { 0x0015, 0x0045 }, + { 0x0015, 0x0046 }, + { 0x0015, 0x0047 }, + { 0x0015, 0x0048 }, + { 0x0015, 0x0049 }, + { 0x0015, 0x004a }, + { 0x0015, 0x004b }, + { 0x0015, 0x004c }, + { 0x0012, 0x0031 }, + { 0x0011, 0x0021 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0012, 0x0032 }, + { 0x0015, 0x004d }, + { 0x0015, 0x004e }, + { 0x0015, 0x004f }, + { 0x0015, 0x0050 }, + { 0x0015, 0x0051 }, + { 0x0015, 0x0052 }, + { 0x0015, 0x0053 }, + { 0x0015, 0x0054 }, + { 0x0015, 0x0055 }, + { 0x0015, 0x0056 }, + { 0x0015, 0x0057 }, + { 0x0015, 0x0058 }, + { 0x0015, 0x0059 }, + { 0x0015, 0x005a }, + { 0x0014, 0x003b }, + { 0x0012, 0x0033 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0015, 0x005b }, + { 0x0015, 0x005c }, + { 0x0015, 0x005d }, + { 0x0015, 0x005e }, + { 0x0015, 0x005f }, + { 0x0015, 0x0060 }, + { 0x0015, 0x0061 }, + { 0x0015, 0x0062 }, + { 0x0015, 0x0063 }, + { 0x0015, 0x0064 }, + { 0x0015, 0x0065 }, + { 0x0015, 0x0066 }, + { 0x0015, 0x0067 }, + { 0x0015, 0x0068 }, + { 0x0015, 0x0069 }, + { 0x0014, 0x003c }, + { 0x0014, 0x003d }, + { 0x0014, 0x003e }, + { 0x0014, 0x003f }, + { 0x0014, 0x0040 }, + { 0x0014, 0x0041 }, + { 0x0014, 0x0042 }, + { 0x0014, 0x0043 }, + { 0x0014, 0x0044 }, + { 0x0014, 0x0045 }, + { 0x0014, 0x0046 }, + { 0x0014, 0x0047 }, + { 0x0014, 0x0048 }, + { 0x0014, 0x0049 }, + { 0x0014, 0x004a }, + { 0x0014, 0x004b }, + { 0x0014, 0x004c }, + { 0x0014, 0x004d }, + { 0x0014, 0x004e }, + { 0x0014, 0x004f }, + { 0x0014, 0x0050 }, + { 0x0014, 0x0051 }, + { 0x0014, 0x0052 }, + { 0x0014, 0x0053 }, + { 0x0014, 0x0054 }, + { 0x0014, 0x0055 }, + { 0x0014, 0x0056 }, + { 0x0014, 0x0057 }, + { 0x0014, 0x0058 }, + { 0x0014, 0x0059 }, + { 0x0014, 0x005a }, + { 0x0014, 0x005b }, + { 0x0014, 0x005c }, + { 0x0014, 0x005d }, + { 0x0014, 0x005e }, + { 0x0014, 0x005f }, + { 0x0014, 0x0060 }, + { 0x0014, 0x0061 }, + { 0x0014, 0x0062 }, + { 0x0014, 0x0063 }, + { 0x0014, 0x0064 }, + { 0x0014, 0x0065 }, + { 0x0014, 0x0066 }, + { 0x0014, 0x0067 }, + { 0x0014, 0x0068 }, + { 0x0014, 0x0069 }, + { 0x0014, 0x006a }, + { 0x0014, 0x006b }, + { 0x0014, 0x006c }, + { 0x0014, 0x006d }, + { 0x0014, 0x006e }, + { 0x0014, 0x006f }, + { 0x0014, 0x0070 }, + { 0x0014, 0x0071 }, + { 0x0014, 0x0072 }, + { 0x0014, 0x0073 }, + { 0x0014, 0x0074 }, + { 0x0014, 0x0075 }, + { 0x0014, 0x0076 }, + { 0x0014, 0x0077 }, + { 0x0014, 0x0078 }, + { 0x0014, 0x0079 }, + { 0x0014, 0x007a }, + { 0x0014, 0x007b }, + { 0x0014, 0x007c }, + { 0x0014, 0x007d }, + { 0x0014, 0x007e }, + { 0x0014, 0x007f }, + { 0x0014, 0x0080 }, + { 0x0014, 0x0081 }, + { 0x0014, 0x0082 }, + { 0x0014, 0x0083 }, + { 0x0014, 0x0084 }, + { 0x0014, 0x0085 }, + { 0x0014, 0x0086 }, + { 0x0014, 0x0087 }, + { 0x0014, 0x0088 }, + { 0x0014, 0x0089 }, + { 0x0014, 0x008a }, + { 0x0014, 0x008b }, + { 0x0014, 0x008c }, + { 0x0014, 0x008d }, + { 0x0014, 0x008e }, + { 0x0014, 0x008f }, + { 0x0014, 0x0090 }, + { 0x0014, 0x0091 }, + { 0x0014, 0x0092 }, + { 0x0014, 0x0093 }, + { 0x0014, 0x0094 }, + { 0x0014, 0x0095 }, + { 0x0014, 0x0096 }, + { 0x0014, 0x0097 }, + { 0x0014, 0x0098 }, + { 0x0014, 0x0099 }, + { 0x0014, 0x009a }, + { 0x0014, 0x009b }, + { 0x0014, 0x009c }, + { 0x0014, 0x009d }, + { 0x0014, 0x009e }, + { 0x0014, 0x009f }, + { 0x0014, 0x00a0 }, + { 0x0014, 0x00a1 }, + { 0x0014, 0x00a2 }, + { 0x0014, 0x00a3 }, + { 0x0014, 0x00a4 }, + { 0x0014, 0x00a5 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc14[400][2] = + { + { 0x0005, 0x0007 }, + { 0x0004, 0x0009 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0006, 0x0006 }, + { 0x0007, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000d, 0x000c }, + { 0x000f, 0x0013 }, + { 0x0010, 0x001b }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0014, 0x0006 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0004, 0x000c }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0006, 0x0007 }, + { 0x0008, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000c, 0x000a }, + { 0x000e, 0x000e }, + { 0x000f, 0x0014 }, + { 0x0011, 0x002a }, + { 0x0012, 0x004a }, + { 0x0013, 0x0084 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0014, 0x0009 }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0014, 0x000c }, + { 0x0005, 0x000c }, + { 0x0004, 0x000d }, + { 0x0004, 0x000e }, + { 0x0005, 0x000d }, + { 0x0006, 0x0008 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0007 }, + { 0x000a, 0x0008 }, + { 0x000c, 0x000b }, + { 0x000e, 0x000f }, + { 0x000f, 0x0015 }, + { 0x0012, 0x004b }, + { 0x0013, 0x0085 }, + { 0x0014, 0x000d }, + { 0x0014, 0x000e }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0014, 0x0013 }, + { 0x0005, 0x000e }, + { 0x0004, 0x000f }, + { 0x0005, 0x000f }, + { 0x0005, 0x0010 }, + { 0x0006, 0x0009 }, + { 0x0008, 0x0008 }, + { 0x0009, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000d, 0x000d }, + { 0x000e, 0x0010 }, + { 0x0010, 0x001c }, + { 0x0011, 0x002b }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + { 0x0014, 0x001a }, + { 0x0014, 0x001b }, + { 0x0006, 0x000a }, + { 0x0005, 0x0011 }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0007, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x000a, 0x0009 }, + { 0x000c, 0x000c }, + { 0x000e, 0x0011 }, + { 0x000f, 0x0016 }, + { 0x0010, 0x001d }, + { 0x0012, 0x004c }, + { 0x0014, 0x001c }, + { 0x0014, 0x001d }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0014, 0x0020 }, + { 0x0014, 0x0021 }, + { 0x0014, 0x0022 }, + { 0x0014, 0x0023 }, + { 0x0007, 0x0009 }, + { 0x0006, 0x000d }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0009, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000b, 0x000a }, + { 0x000d, 0x000e }, + { 0x000f, 0x0017 }, + { 0x0011, 0x002c }, + { 0x0010, 0x001e }, + { 0x0014, 0x0024 }, + { 0x0014, 0x0025 }, + { 0x0014, 0x0026 }, + { 0x0014, 0x0027 }, + { 0x0014, 0x0028 }, + { 0x0014, 0x0029 }, + { 0x0014, 0x002a }, + { 0x0014, 0x002b }, + { 0x0014, 0x002c }, + { 0x0009, 0x000a }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0009, 0x000b }, + { 0x000a, 0x000b }, + { 0x000b, 0x000b }, + { 0x000d, 0x000f }, + { 0x000e, 0x0012 }, + { 0x000f, 0x0018 }, + { 0x0011, 0x002d }, + { 0x0011, 0x002e }, + { 0x0013, 0x0086 }, + { 0x0014, 0x002d }, + { 0x0014, 0x002e }, + { 0x0014, 0x002f }, + { 0x0014, 0x0030 }, + { 0x0014, 0x0031 }, + { 0x0014, 0x0032 }, + { 0x0014, 0x0033 }, + { 0x0014, 0x0034 }, + { 0x000b, 0x000c }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000b, 0x000d }, + { 0x000c, 0x000d }, + { 0x000d, 0x0010 }, + { 0x000e, 0x0013 }, + { 0x000f, 0x0019 }, + { 0x0010, 0x001f }, + { 0x0013, 0x0087 }, + { 0x0014, 0x0035 }, + { 0x0014, 0x0036 }, + { 0x0013, 0x0088 }, + { 0x0014, 0x0037 }, + { 0x0014, 0x0038 }, + { 0x0014, 0x0039 }, + { 0x0014, 0x003a }, + { 0x0014, 0x003b }, + { 0x0014, 0x003c }, + { 0x0014, 0x003d }, + { 0x000d, 0x0011 }, + { 0x000c, 0x000e }, + { 0x000c, 0x000f }, + { 0x000d, 0x0012 }, + { 0x000d, 0x0013 }, + { 0x000e, 0x0014 }, + { 0x0010, 0x0020 }, + { 0x0010, 0x0021 }, + { 0x0012, 0x004d }, + { 0x0011, 0x002f }, + { 0x0014, 0x003e }, + { 0x0014, 0x003f }, + { 0x0014, 0x0040 }, + { 0x0014, 0x0041 }, + { 0x0014, 0x0042 }, + { 0x0014, 0x0043 }, + { 0x0014, 0x0044 }, + { 0x0014, 0x0045 }, + { 0x0014, 0x0046 }, + { 0x0014, 0x0047 }, + { 0x000f, 0x001a }, + { 0x000e, 0x0015 }, + { 0x000e, 0x0016 }, + { 0x000e, 0x0017 }, + { 0x000f, 0x001b }, + { 0x0011, 0x0030 }, + { 0x0011, 0x0031 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x0013, 0x008b }, + { 0x0014, 0x0048 }, + { 0x0014, 0x0049 }, + { 0x0014, 0x004a }, + { 0x0014, 0x004b }, + { 0x0014, 0x004c }, + { 0x0014, 0x004d }, + { 0x0014, 0x004e }, + { 0x0014, 0x004f }, + { 0x0014, 0x0050 }, + { 0x0014, 0x0051 }, + { 0x0010, 0x0022 }, + { 0x0010, 0x0023 }, + { 0x0010, 0x0024 }, + { 0x0010, 0x0025 }, + { 0x0011, 0x0032 }, + { 0x0011, 0x0033 }, + { 0x0012, 0x004e }, + { 0x0012, 0x004f }, + { 0x0014, 0x0052 }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0014, 0x0053 }, + { 0x0014, 0x0054 }, + { 0x0014, 0x0055 }, + { 0x0014, 0x0056 }, + { 0x0014, 0x0057 }, + { 0x0014, 0x0058 }, + { 0x0014, 0x0059 }, + { 0x0014, 0x005a }, + { 0x0014, 0x005b }, + { 0x0011, 0x0034 }, + { 0x0011, 0x0035 }, + { 0x0012, 0x0050 }, + { 0x0012, 0x0051 }, + { 0x0013, 0x008e }, + { 0x0014, 0x005c }, + { 0x0014, 0x005d }, + { 0x0014, 0x005e }, + { 0x0014, 0x005f }, + { 0x0014, 0x0060 }, + { 0x0014, 0x0061 }, + { 0x0014, 0x0062 }, + { 0x0014, 0x0063 }, + { 0x0014, 0x0064 }, + { 0x0014, 0x0065 }, + { 0x0014, 0x0066 }, + { 0x0014, 0x0067 }, + { 0x0014, 0x0068 }, + { 0x0014, 0x0069 }, + { 0x0014, 0x006a }, + { 0x0012, 0x0052 }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0014, 0x006b }, + { 0x0013, 0x0091 }, + { 0x0014, 0x006c }, + { 0x0014, 0x006d }, + { 0x0014, 0x006e }, + { 0x0014, 0x006f }, + { 0x0014, 0x0070 }, + { 0x0014, 0x0071 }, + { 0x0014, 0x0072 }, + { 0x0014, 0x0073 }, + { 0x0014, 0x0074 }, + { 0x0014, 0x0075 }, + { 0x0014, 0x0076 }, + { 0x0014, 0x0077 }, + { 0x0014, 0x0078 }, + { 0x0014, 0x0079 }, + { 0x0014, 0x007a }, + { 0x0014, 0x007b }, + { 0x0014, 0x007c }, + { 0x0013, 0x0092 }, + { 0x0012, 0x0053 }, + { 0x0014, 0x007d }, + { 0x0014, 0x007e }, + { 0x0014, 0x007f }, + { 0x0014, 0x0080 }, + { 0x0014, 0x0081 }, + { 0x0014, 0x0082 }, + { 0x0014, 0x0083 }, + { 0x0014, 0x0084 }, + { 0x0014, 0x0085 }, + { 0x0014, 0x0086 }, + { 0x0014, 0x0087 }, + { 0x0014, 0x0088 }, + { 0x0014, 0x0089 }, + { 0x0014, 0x008a }, + { 0x0014, 0x008b }, + { 0x0014, 0x008c }, + { 0x0014, 0x008d }, + { 0x0014, 0x008e }, + { 0x0013, 0x0093 }, + { 0x0014, 0x008f }, + { 0x0014, 0x0090 }, + { 0x0014, 0x0091 }, + { 0x0014, 0x0092 }, + { 0x0014, 0x0093 }, + { 0x0014, 0x0094 }, + { 0x0014, 0x0095 }, + { 0x0014, 0x0096 }, + { 0x0014, 0x0097 }, + { 0x0014, 0x0098 }, + { 0x0014, 0x0099 }, + { 0x0014, 0x009a }, + { 0x0014, 0x009b }, + { 0x0014, 0x009c }, + { 0x0014, 0x009d }, + { 0x0014, 0x009e }, + { 0x0014, 0x009f }, + { 0x0014, 0x00a0 }, + { 0x0014, 0x00a1 }, + { 0x0014, 0x00a2 }, + { 0x0014, 0x00a3 }, + { 0x0014, 0x00a4 }, + { 0x0014, 0x00a5 }, + { 0x0014, 0x00a6 }, + { 0x0014, 0x00a7 }, + { 0x0014, 0x00a8 }, + { 0x0014, 0x00a9 }, + { 0x0014, 0x00aa }, + { 0x0014, 0x00ab }, + { 0x0014, 0x00ac }, + { 0x0014, 0x00ad }, + { 0x0014, 0x00ae }, + { 0x0014, 0x00af }, + { 0x0014, 0x00b0 }, + { 0x0014, 0x00b1 }, + { 0x0014, 0x00b2 }, + { 0x0014, 0x00b3 }, + { 0x0014, 0x00b4 }, + { 0x0014, 0x00b5 }, + { 0x0014, 0x00b6 }, + { 0x0014, 0x00b7 }, + { 0x0014, 0x00b8 }, + { 0x0014, 0x00b9 }, + { 0x0014, 0x00ba }, + { 0x0014, 0x00bb }, + { 0x0014, 0x00bc }, + { 0x0014, 0x00bd }, + { 0x0014, 0x00be }, + { 0x0014, 0x00bf }, + { 0x0014, 0x00c0 }, + { 0x0014, 0x00c1 }, + { 0x0014, 0x00c2 }, + { 0x0014, 0x00c3 }, + { 0x0014, 0x00c4 }, + { 0x0014, 0x00c5 }, + { 0x0014, 0x00c6 }, + { 0x0014, 0x00c7 }, + { 0x0014, 0x00c8 }, + { 0x0014, 0x00c9 }, + { 0x0014, 0x00ca }, + { 0x0014, 0x00cb }, + { 0x0014, 0x00cc }, + { 0x0014, 0x00cd }, + { 0x0014, 0x00ce }, + { 0x0014, 0x00cf }, + { 0x0014, 0x00d0 }, + { 0x0014, 0x00d1 }, + { 0x0014, 0x00d2 }, + { 0x0014, 0x00d3 }, + { 0x0014, 0x00d4 }, + { 0x0014, 0x00d5 }, + { 0x0014, 0x00d6 }, + { 0x0014, 0x00d7 }, + { 0x0014, 0x00d8 }, + { 0x0014, 0x00d9 }, + { 0x0014, 0x00da }, + { 0x0014, 0x00db }, + { 0x0014, 0x00dc }, + { 0x0014, 0x00dd }, + { 0x0014, 0x00de }, + { 0x0014, 0x00df }, + { 0x0014, 0x00e0 }, + { 0x0014, 0x00e1 }, + { 0x0014, 0x00e2 }, + { 0x0014, 0x00e3 }, + { 0x0014, 0x00e4 }, + { 0x0014, 0x00e5 }, + { 0x0014, 0x00e6 }, + { 0x0014, 0x00e7 }, + { 0x0014, 0x00e8 }, + { 0x0014, 0x00e9 }, + { 0x0014, 0x00ea }, + { 0x0014, 0x00eb }, + { 0x0014, 0x00ec }, + { 0x0014, 0x00ed }, + { 0x0014, 0x00ee }, + { 0x0014, 0x00ef }, + { 0x0014, 0x00f0 }, + { 0x0014, 0x00f1 }, + { 0x0014, 0x00f2 }, + { 0x0014, 0x00f3 }, + { 0x0014, 0x00f4 }, + { 0x0014, 0x00f5 }, + { 0x0014, 0x00f6 }, + { 0x0014, 0x00f7 }, + { 0x0014, 0x00f8 }, + { 0x0014, 0x00f9 }, + { 0x0014, 0x00fa }, + { 0x0014, 0x00fb }, + { 0x0014, 0x00fc }, + { 0x0014, 0x00fd }, + { 0x0014, 0x00fe }, + { 0x0014, 0x00ff }, + { 0x0014, 0x0100 }, + { 0x0014, 0x0101 }, + { 0x0014, 0x0102 }, + { 0x0014, 0x0103 }, + }; + +const uint16_t c_aauiLCLDHuffEnc15[576][2] = + { + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0007, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0009, 0x0008 }, + { 0x000b, 0x000b }, + { 0x000d, 0x000e }, + { 0x000e, 0x0011 }, + { 0x000f, 0x001a }, + { 0x0012, 0x006e }, + { 0x0014, 0x0000 }, + { 0x0013, 0x00cc }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0014, 0x0006 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0014, 0x0009 }, + { 0x0005, 0x000d }, + { 0x0004, 0x000c }, + { 0x0004, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0006, 0x000b }, + { 0x0007, 0x0009 }, + { 0x0008, 0x000a }, + { 0x000a, 0x000a }, + { 0x000c, 0x000c }, + { 0x000d, 0x000f }, + { 0x000f, 0x001b }, + { 0x0011, 0x003d }, + { 0x0011, 0x003e }, + { 0x0013, 0x00cd }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0014, 0x000c }, + { 0x0014, 0x000d }, + { 0x0014, 0x000e }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0005, 0x0010 }, + { 0x0004, 0x000e }, + { 0x0004, 0x000f }, + { 0x0005, 0x0011 }, + { 0x0005, 0x0012 }, + { 0x0006, 0x000c }, + { 0x0007, 0x000a }, + { 0x0009, 0x0009 }, + { 0x000a, 0x000b }, + { 0x000c, 0x000d }, + { 0x000e, 0x0012 }, + { 0x0010, 0x0027 }, + { 0x0011, 0x003f }, + { 0x0012, 0x006f }, + { 0x0014, 0x0013 }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + { 0x0014, 0x001a }, + { 0x0014, 0x001b }, + { 0x0014, 0x001c }, + { 0x0006, 0x000d }, + { 0x0005, 0x0013 }, + { 0x0005, 0x0014 }, + { 0x0005, 0x0015 }, + { 0x0006, 0x000e }, + { 0x0007, 0x000b }, + { 0x0008, 0x000b }, + { 0x0009, 0x000a }, + { 0x000b, 0x000c }, + { 0x000c, 0x000e }, + { 0x000e, 0x0013 }, + { 0x000f, 0x001c }, + { 0x0011, 0x0040 }, + { 0x0012, 0x0070 }, + { 0x0014, 0x001d }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0014, 0x0020 }, + { 0x0014, 0x0021 }, + { 0x0014, 0x0022 }, + { 0x0014, 0x0023 }, + { 0x0014, 0x0024 }, + { 0x0014, 0x0025 }, + { 0x0014, 0x0026 }, + { 0x0006, 0x000f }, + { 0x0005, 0x0016 }, + { 0x0005, 0x0017 }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0007, 0x000c }, + { 0x0009, 0x000b }, + { 0x000a, 0x000c }, + { 0x000b, 0x000d }, + { 0x000d, 0x0010 }, + { 0x000e, 0x0014 }, + { 0x0010, 0x0028 }, + { 0x0011, 0x0041 }, + { 0x0013, 0x00ce }, + { 0x0014, 0x0027 }, + { 0x0014, 0x0028 }, + { 0x0014, 0x0029 }, + { 0x0014, 0x002a }, + { 0x0014, 0x002b }, + { 0x0014, 0x002c }, + { 0x0014, 0x002d }, + { 0x0014, 0x002e }, + { 0x0014, 0x002f }, + { 0x0014, 0x0030 }, + { 0x0007, 0x000d }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0008, 0x000c }, + { 0x0009, 0x000c }, + { 0x000b, 0x000e }, + { 0x000c, 0x000f }, + { 0x000e, 0x0015 }, + { 0x0010, 0x0029 }, + { 0x0011, 0x0042 }, + { 0x0014, 0x0031 }, + { 0x0014, 0x0032 }, + { 0x0014, 0x0033 }, + { 0x0014, 0x0034 }, + { 0x0014, 0x0035 }, + { 0x0014, 0x0036 }, + { 0x0014, 0x0037 }, + { 0x0014, 0x0038 }, + { 0x0014, 0x0039 }, + { 0x0014, 0x003a }, + { 0x0014, 0x003b }, + { 0x0014, 0x003c }, + { 0x0008, 0x000d }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0008, 0x000e }, + { 0x0009, 0x000d }, + { 0x0009, 0x000e }, + { 0x000b, 0x000f }, + { 0x000c, 0x0010 }, + { 0x000d, 0x0011 }, + { 0x000f, 0x001d }, + { 0x0010, 0x002a }, + { 0x0011, 0x0043 }, + { 0x0014, 0x003d }, + { 0x0013, 0x00cf }, + { 0x0014, 0x003e }, + { 0x0014, 0x003f }, + { 0x0014, 0x0040 }, + { 0x0014, 0x0041 }, + { 0x0014, 0x0042 }, + { 0x0014, 0x0043 }, + { 0x0014, 0x0044 }, + { 0x0014, 0x0045 }, + { 0x0014, 0x0046 }, + { 0x0014, 0x0047 }, + { 0x0009, 0x000f }, + { 0x0008, 0x000f }, + { 0x0009, 0x0010 }, + { 0x0009, 0x0011 }, + { 0x000a, 0x000d }, + { 0x000b, 0x0010 }, + { 0x000c, 0x0011 }, + { 0x000d, 0x0012 }, + { 0x000e, 0x0016 }, + { 0x0010, 0x002b }, + { 0x0011, 0x0044 }, + { 0x0012, 0x0071 }, + { 0x0014, 0x0048 }, + { 0x0014, 0x0049 }, + { 0x0014, 0x004a }, + { 0x0014, 0x004b }, + { 0x0014, 0x004c }, + { 0x0014, 0x004d }, + { 0x0014, 0x004e }, + { 0x0014, 0x004f }, + { 0x0014, 0x0050 }, + { 0x0014, 0x0051 }, + { 0x0014, 0x0052 }, + { 0x0014, 0x0053 }, + { 0x000b, 0x0011 }, + { 0x000a, 0x000e }, + { 0x000a, 0x000f }, + { 0x000b, 0x0012 }, + { 0x000b, 0x0013 }, + { 0x000c, 0x0012 }, + { 0x000d, 0x0013 }, + { 0x000e, 0x0017 }, + { 0x0010, 0x002c }, + { 0x0012, 0x0072 }, + { 0x0011, 0x0045 }, + { 0x0013, 0x00d0 }, + { 0x0013, 0x00d1 }, + { 0x0014, 0x0054 }, + { 0x0014, 0x0055 }, + { 0x0014, 0x0056 }, + { 0x0014, 0x0057 }, + { 0x0014, 0x0058 }, + { 0x0014, 0x0059 }, + { 0x0014, 0x005a }, + { 0x0014, 0x005b }, + { 0x0014, 0x005c }, + { 0x0014, 0x005d }, + { 0x0014, 0x005e }, + { 0x000c, 0x0013 }, + { 0x000c, 0x0014 }, + { 0x000c, 0x0015 }, + { 0x000d, 0x0014 }, + { 0x000d, 0x0015 }, + { 0x000e, 0x0018 }, + { 0x000f, 0x001e }, + { 0x0010, 0x002d }, + { 0x0011, 0x0046 }, + { 0x0011, 0x0047 }, + { 0x0011, 0x0048 }, + { 0x0014, 0x005f }, + { 0x0014, 0x0060 }, + { 0x0014, 0x0061 }, + { 0x0014, 0x0062 }, + { 0x0014, 0x0063 }, + { 0x0014, 0x0064 }, + { 0x0014, 0x0065 }, + { 0x0014, 0x0066 }, + { 0x0014, 0x0067 }, + { 0x0014, 0x0068 }, + { 0x0014, 0x0069 }, + { 0x0014, 0x006a }, + { 0x0014, 0x006b }, + { 0x000e, 0x0019 }, + { 0x000d, 0x0016 }, + { 0x000d, 0x0017 }, + { 0x000e, 0x001a }, + { 0x000e, 0x001b }, + { 0x000f, 0x001f }, + { 0x0010, 0x002e }, + { 0x0011, 0x0049 }, + { 0x0012, 0x0073 }, + { 0x0014, 0x006c }, + { 0x0014, 0x006d }, + { 0x0014, 0x006e }, + { 0x0014, 0x006f }, + { 0x0014, 0x0070 }, + { 0x0014, 0x0071 }, + { 0x0014, 0x0072 }, + { 0x0014, 0x0073 }, + { 0x0014, 0x0074 }, + { 0x0014, 0x0075 }, + { 0x0014, 0x0076 }, + { 0x0014, 0x0077 }, + { 0x0014, 0x0078 }, + { 0x0014, 0x0079 }, + { 0x0014, 0x007a }, + { 0x0010, 0x002f }, + { 0x000f, 0x0020 }, + { 0x0010, 0x0030 }, + { 0x000f, 0x0021 }, + { 0x0010, 0x0031 }, + { 0x0011, 0x004a }, + { 0x0011, 0x004b }, + { 0x0012, 0x0074 }, + { 0x0014, 0x007b }, + { 0x0014, 0x007c }, + { 0x0013, 0x00d2 }, + { 0x0014, 0x007d }, + { 0x0014, 0x007e }, + { 0x0014, 0x007f }, + { 0x0014, 0x0080 }, + { 0x0014, 0x0081 }, + { 0x0014, 0x0082 }, + { 0x0014, 0x0083 }, + { 0x0014, 0x0084 }, + { 0x0014, 0x0085 }, + { 0x0014, 0x0086 }, + { 0x0014, 0x0087 }, + { 0x0014, 0x0088 }, + { 0x0014, 0x0089 }, + { 0x0012, 0x0075 }, + { 0x0010, 0x0032 }, + { 0x0010, 0x0033 }, + { 0x0011, 0x004c }, + { 0x0011, 0x004d }, + { 0x0013, 0x00d3 }, + { 0x0013, 0x00d4 }, + { 0x0012, 0x0076 }, + { 0x0013, 0x00d5 }, + { 0x0014, 0x008a }, + { 0x0014, 0x008b }, + { 0x0014, 0x008c }, + { 0x0014, 0x008d }, + { 0x0014, 0x008e }, + { 0x0014, 0x008f }, + { 0x0014, 0x0090 }, + { 0x0014, 0x0091 }, + { 0x0014, 0x0092 }, + { 0x0014, 0x0093 }, + { 0x0014, 0x0094 }, + { 0x0014, 0x0095 }, + { 0x0014, 0x0096 }, + { 0x0014, 0x0097 }, + { 0x0014, 0x0098 }, + { 0x0013, 0x00d6 }, + { 0x0013, 0x00d7 }, + { 0x0012, 0x0077 }, + { 0x0012, 0x0078 }, + { 0x0014, 0x0099 }, + { 0x0014, 0x009a }, + { 0x0013, 0x00d8 }, + { 0x0014, 0x009b }, + { 0x0014, 0x009c }, + { 0x0014, 0x009d }, + { 0x0014, 0x009e }, + { 0x0014, 0x009f }, + { 0x0014, 0x00a0 }, + { 0x0014, 0x00a1 }, + { 0x0014, 0x00a2 }, + { 0x0014, 0x00a3 }, + { 0x0014, 0x00a4 }, + { 0x0014, 0x00a5 }, + { 0x0014, 0x00a6 }, + { 0x0014, 0x00a7 }, + { 0x0014, 0x00a8 }, + { 0x0014, 0x00a9 }, + { 0x0014, 0x00aa }, + { 0x0014, 0x00ab }, + { 0x0014, 0x00ac }, + { 0x0014, 0x00ad }, + { 0x0014, 0x00ae }, + { 0x0014, 0x00af }, + { 0x0012, 0x0079 }, + { 0x0014, 0x00b0 }, + { 0x0014, 0x00b1 }, + { 0x0014, 0x00b2 }, + { 0x0014, 0x00b3 }, + { 0x0014, 0x00b4 }, + { 0x0014, 0x00b5 }, + { 0x0014, 0x00b6 }, + { 0x0014, 0x00b7 }, + { 0x0014, 0x00b8 }, + { 0x0014, 0x00b9 }, + { 0x0014, 0x00ba }, + { 0x0014, 0x00bb }, + { 0x0014, 0x00bc }, + { 0x0014, 0x00bd }, + { 0x0014, 0x00be }, + { 0x0014, 0x00bf }, + { 0x0014, 0x00c0 }, + { 0x0014, 0x00c1 }, + { 0x0014, 0x00c2 }, + { 0x0014, 0x00c3 }, + { 0x0014, 0x00c4 }, + { 0x0014, 0x00c5 }, + { 0x0014, 0x00c6 }, + { 0x0013, 0x00d9 }, + { 0x0013, 0x00da }, + { 0x0014, 0x00c7 }, + { 0x0014, 0x00c8 }, + { 0x0014, 0x00c9 }, + { 0x0014, 0x00ca }, + { 0x0014, 0x00cb }, + { 0x0014, 0x00cc }, + { 0x0014, 0x00cd }, + { 0x0014, 0x00ce }, + { 0x0014, 0x00cf }, + { 0x0014, 0x00d0 }, + { 0x0014, 0x00d1 }, + { 0x0014, 0x00d2 }, + { 0x0014, 0x00d3 }, + { 0x0014, 0x00d4 }, + { 0x0014, 0x00d5 }, + { 0x0014, 0x00d6 }, + { 0x0014, 0x00d7 }, + { 0x0014, 0x00d8 }, + { 0x0014, 0x00d9 }, + { 0x0014, 0x00da }, + { 0x0014, 0x00db }, + { 0x0014, 0x00dc }, + { 0x0014, 0x00dd }, + { 0x0014, 0x00de }, + { 0x0014, 0x00df }, + { 0x0014, 0x00e0 }, + { 0x0014, 0x00e1 }, + { 0x0014, 0x00e2 }, + { 0x0014, 0x00e3 }, + { 0x0014, 0x00e4 }, + { 0x0014, 0x00e5 }, + { 0x0014, 0x00e6 }, + { 0x0014, 0x00e7 }, + { 0x0014, 0x00e8 }, + { 0x0014, 0x00e9 }, + { 0x0014, 0x00ea }, + { 0x0014, 0x00eb }, + { 0x0014, 0x00ec }, + { 0x0014, 0x00ed }, + { 0x0014, 0x00ee }, + { 0x0014, 0x00ef }, + { 0x0014, 0x00f0 }, + { 0x0014, 0x00f1 }, + { 0x0014, 0x00f2 }, + { 0x0014, 0x00f3 }, + { 0x0014, 0x00f4 }, + { 0x0014, 0x00f5 }, + { 0x0014, 0x00f6 }, + { 0x0014, 0x00f7 }, + { 0x0014, 0x00f8 }, + { 0x0014, 0x00f9 }, + { 0x0014, 0x00fa }, + { 0x0014, 0x00fb }, + { 0x0014, 0x00fc }, + { 0x0014, 0x00fd }, + { 0x0014, 0x00fe }, + { 0x0014, 0x00ff }, + { 0x0014, 0x0100 }, + { 0x0014, 0x0101 }, + { 0x0014, 0x0102 }, + { 0x0014, 0x0103 }, + { 0x0014, 0x0104 }, + { 0x0014, 0x0105 }, + { 0x0014, 0x0106 }, + { 0x0014, 0x0107 }, + { 0x0014, 0x0108 }, + { 0x0014, 0x0109 }, + { 0x0014, 0x010a }, + { 0x0014, 0x010b }, + { 0x0014, 0x010c }, + { 0x0014, 0x010d }, + { 0x0014, 0x010e }, + { 0x0014, 0x010f }, + { 0x0014, 0x0110 }, + { 0x0014, 0x0111 }, + { 0x0014, 0x0112 }, + { 0x0014, 0x0113 }, + { 0x0014, 0x0114 }, + { 0x0014, 0x0115 }, + { 0x0014, 0x0116 }, + { 0x0014, 0x0117 }, + { 0x0014, 0x0118 }, + { 0x0014, 0x0119 }, + { 0x0014, 0x011a }, + { 0x0014, 0x011b }, + { 0x0014, 0x011c }, + { 0x0014, 0x011d }, + { 0x0014, 0x011e }, + { 0x0014, 0x011f }, + { 0x0014, 0x0120 }, + { 0x0014, 0x0121 }, + { 0x0014, 0x0122 }, + { 0x0014, 0x0123 }, + { 0x0014, 0x0124 }, + { 0x0014, 0x0125 }, + { 0x0014, 0x0126 }, + { 0x0014, 0x0127 }, + { 0x0014, 0x0128 }, + { 0x0014, 0x0129 }, + { 0x0014, 0x012a }, + { 0x0014, 0x012b }, + { 0x0014, 0x012c }, + { 0x0014, 0x012d }, + { 0x0014, 0x012e }, + { 0x0014, 0x012f }, + { 0x0014, 0x0130 }, + { 0x0014, 0x0131 }, + { 0x0014, 0x0132 }, + { 0x0014, 0x0133 }, + { 0x0014, 0x0134 }, + { 0x0014, 0x0135 }, + { 0x0014, 0x0136 }, + { 0x0014, 0x0137 }, + { 0x0014, 0x0138 }, + { 0x0014, 0x0139 }, + { 0x0014, 0x013a }, + { 0x0014, 0x013b }, + { 0x0014, 0x013c }, + { 0x0014, 0x013d }, + { 0x0014, 0x013e }, + { 0x0014, 0x013f }, + { 0x0014, 0x0140 }, + { 0x0014, 0x0141 }, + { 0x0014, 0x0142 }, + { 0x0014, 0x0143 }, + { 0x0014, 0x0144 }, + { 0x0014, 0x0145 }, + { 0x0014, 0x0146 }, + { 0x0014, 0x0147 }, + { 0x0014, 0x0148 }, + { 0x0014, 0x0149 }, + { 0x0014, 0x014a }, + { 0x0014, 0x014b }, + { 0x0014, 0x014c }, + { 0x0014, 0x014d }, + { 0x0014, 0x014e }, + { 0x0014, 0x014f }, + { 0x0014, 0x0150 }, + { 0x0014, 0x0151 }, + { 0x0014, 0x0152 }, + { 0x0014, 0x0153 }, + { 0x0014, 0x0154 }, + { 0x0014, 0x0155 }, + { 0x0014, 0x0156 }, + { 0x0014, 0x0157 }, + { 0x0014, 0x0158 }, + { 0x0014, 0x0159 }, + { 0x0014, 0x015a }, + { 0x0014, 0x015b }, + { 0x0014, 0x015c }, + { 0x0014, 0x015d }, + { 0x0014, 0x015e }, + { 0x0014, 0x015f }, + { 0x0014, 0x0160 }, + { 0x0014, 0x0161 }, + { 0x0014, 0x0162 }, + { 0x0014, 0x0163 }, + { 0x0014, 0x0164 }, + { 0x0014, 0x0165 }, + { 0x0014, 0x0166 }, + { 0x0014, 0x0167 }, + { 0x0014, 0x0168 }, + { 0x0014, 0x0169 }, + { 0x0014, 0x016a }, + { 0x0014, 0x016b }, + { 0x0014, 0x016c }, + { 0x0014, 0x016d }, + { 0x0014, 0x016e }, + { 0x0014, 0x016f }, + { 0x0014, 0x0170 }, + { 0x0014, 0x0171 }, + { 0x0014, 0x0172 }, + { 0x0014, 0x0173 }, + { 0x0014, 0x0174 }, + { 0x0014, 0x0175 }, + { 0x0014, 0x0176 }, + { 0x0014, 0x0177 }, + { 0x0014, 0x0178 }, + { 0x0014, 0x0179 }, + { 0x0014, 0x017a }, + { 0x0014, 0x017b }, + { 0x0014, 0x017c }, + { 0x0014, 0x017d }, + { 0x0014, 0x017e }, + { 0x0014, 0x017f }, + { 0x0014, 0x0180 }, + { 0x0014, 0x0181 }, + { 0x0014, 0x0182 }, + { 0x0014, 0x0183 }, + { 0x0014, 0x0184 }, + { 0x0014, 0x0185 }, + { 0x0014, 0x0186 }, + { 0x0014, 0x0187 }, + { 0x0014, 0x0188 }, + { 0x0014, 0x0189 }, + { 0x0014, 0x018a }, + { 0x0014, 0x018b }, + { 0x0014, 0x018c }, + { 0x0014, 0x018d }, + { 0x0014, 0x018e }, + { 0x0014, 0x018f }, + { 0x0014, 0x0190 }, + { 0x0014, 0x0191 }, + { 0x0014, 0x0192 }, + { 0x0014, 0x0193 }, + { 0x0014, 0x0194 }, + { 0x0014, 0x0195 }, + { 0x0014, 0x0196 }, + { 0x0014, 0x0197 }, + { 0x0013, 0x00db }, + }; + +const uint16_t c_aauiLCLDHuffEnc16[729][2] = + { + { 0x0006, 0x000d }, + { 0x0005, 0x0010 }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0008, 0x000a }, + { 0x0009, 0x000b }, + { 0x000b, 0x000d }, + { 0x000c, 0x000e }, + { 0x000e, 0x0016 }, + { 0x0010, 0x002d }, + { 0x0011, 0x0051 }, + { 0x0012, 0x008c }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0014, 0x0006 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0014, 0x0009 }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0005, 0x0011 }, + { 0x0004, 0x000f }, + { 0x0005, 0x0012 }, + { 0x0005, 0x0013 }, + { 0x0005, 0x0014 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0007, 0x000c }, + { 0x0008, 0x000b }, + { 0x000a, 0x000c }, + { 0x000b, 0x000e }, + { 0x000d, 0x0010 }, + { 0x000e, 0x0017 }, + { 0x000f, 0x001c }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0014, 0x000c }, + { 0x0014, 0x000d }, + { 0x0014, 0x000e }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0014, 0x0013 }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0006, 0x0013 }, + { 0x0005, 0x0015 }, + { 0x0005, 0x0016 }, + { 0x0005, 0x0017 }, + { 0x0005, 0x0018 }, + { 0x0006, 0x0014 }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0009, 0x000c }, + { 0x000a, 0x000d }, + { 0x000c, 0x000f }, + { 0x000d, 0x0011 }, + { 0x000f, 0x001d }, + { 0x0011, 0x0052 }, + { 0x0012, 0x008d }, + { 0x0012, 0x008e }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + { 0x0014, 0x001a }, + { 0x0014, 0x001b }, + { 0x0014, 0x001c }, + { 0x0014, 0x001d }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0014, 0x0020 }, + { 0x0014, 0x0021 }, + { 0x0006, 0x0015 }, + { 0x0005, 0x0019 }, + { 0x0005, 0x001a }, + { 0x0005, 0x001b }, + { 0x0006, 0x0016 }, + { 0x0006, 0x0017 }, + { 0x0007, 0x000f }, + { 0x0008, 0x000c }, + { 0x0009, 0x000d }, + { 0x000b, 0x000f }, + { 0x000c, 0x0010 }, + { 0x000d, 0x0012 }, + { 0x000f, 0x001e }, + { 0x0012, 0x008f }, + { 0x0014, 0x0022 }, + { 0x0014, 0x0023 }, + { 0x0014, 0x0024 }, + { 0x0014, 0x0025 }, + { 0x0014, 0x0026 }, + { 0x0014, 0x0027 }, + { 0x0014, 0x0028 }, + { 0x0014, 0x0029 }, + { 0x0014, 0x002a }, + { 0x0014, 0x002b }, + { 0x0014, 0x002c }, + { 0x0014, 0x002d }, + { 0x0014, 0x002e }, + { 0x0006, 0x0018 }, + { 0x0005, 0x001c }, + { 0x0005, 0x001d }, + { 0x0006, 0x0019 }, + { 0x0006, 0x001a }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0008, 0x000d }, + { 0x000a, 0x000e }, + { 0x000b, 0x0010 }, + { 0x000c, 0x0011 }, + { 0x000e, 0x0018 }, + { 0x0010, 0x002e }, + { 0x0012, 0x0090 }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0014, 0x002f }, + { 0x0014, 0x0030 }, + { 0x0014, 0x0031 }, + { 0x0014, 0x0032 }, + { 0x0014, 0x0033 }, + { 0x0014, 0x0034 }, + { 0x0014, 0x0035 }, + { 0x0014, 0x0036 }, + { 0x0014, 0x0037 }, + { 0x0014, 0x0038 }, + { 0x0014, 0x0039 }, + { 0x0007, 0x0012 }, + { 0x0006, 0x001b }, + { 0x0006, 0x001c }, + { 0x0006, 0x001d }, + { 0x0007, 0x0013 }, + { 0x0007, 0x0014 }, + { 0x0008, 0x000e }, + { 0x0009, 0x000e }, + { 0x000b, 0x0011 }, + { 0x000c, 0x0012 }, + { 0x000d, 0x0013 }, + { 0x000e, 0x0019 }, + { 0x0010, 0x002f }, + { 0x0012, 0x0091 }, + { 0x0014, 0x003a }, + { 0x0014, 0x003b }, + { 0x0014, 0x003c }, + { 0x0014, 0x003d }, + { 0x0014, 0x003e }, + { 0x0014, 0x003f }, + { 0x0014, 0x0040 }, + { 0x0014, 0x0041 }, + { 0x0014, 0x0042 }, + { 0x0014, 0x0043 }, + { 0x0014, 0x0044 }, + { 0x0014, 0x0045 }, + { 0x0014, 0x0046 }, + { 0x0007, 0x0015 }, + { 0x0006, 0x001e }, + { 0x0006, 0x001f }, + { 0x0007, 0x0016 }, + { 0x0007, 0x0017 }, + { 0x0008, 0x000f }, + { 0x0009, 0x000f }, + { 0x000a, 0x000f }, + { 0x000b, 0x0012 }, + { 0x000d, 0x0014 }, + { 0x000e, 0x001a }, + { 0x000f, 0x001f }, + { 0x0013, 0x010f }, + { 0x0011, 0x0053 }, + { 0x0014, 0x0047 }, + { 0x0014, 0x0048 }, + { 0x0014, 0x0049 }, + { 0x0014, 0x004a }, + { 0x0014, 0x004b }, + { 0x0014, 0x004c }, + { 0x0014, 0x004d }, + { 0x0014, 0x004e }, + { 0x0014, 0x004f }, + { 0x0014, 0x0050 }, + { 0x0014, 0x0051 }, + { 0x0014, 0x0052 }, + { 0x0014, 0x0053 }, + { 0x0008, 0x0010 }, + { 0x0007, 0x0018 }, + { 0x0007, 0x0019 }, + { 0x0008, 0x0011 }, + { 0x0008, 0x0012 }, + { 0x0009, 0x0010 }, + { 0x000a, 0x0010 }, + { 0x000b, 0x0013 }, + { 0x000c, 0x0013 }, + { 0x000e, 0x001b }, + { 0x000f, 0x0020 }, + { 0x0010, 0x0030 }, + { 0x0012, 0x0092 }, + { 0x0014, 0x0054 }, + { 0x0014, 0x0055 }, + { 0x0014, 0x0056 }, + { 0x0014, 0x0057 }, + { 0x0014, 0x0058 }, + { 0x0014, 0x0059 }, + { 0x0014, 0x005a }, + { 0x0014, 0x005b }, + { 0x0014, 0x005c }, + { 0x0014, 0x005d }, + { 0x0014, 0x005e }, + { 0x0014, 0x005f }, + { 0x0014, 0x0060 }, + { 0x0014, 0x0061 }, + { 0x0009, 0x0011 }, + { 0x0008, 0x0013 }, + { 0x0009, 0x0012 }, + { 0x0009, 0x0013 }, + { 0x000a, 0x0011 }, + { 0x000a, 0x0012 }, + { 0x000b, 0x0014 }, + { 0x000c, 0x0014 }, + { 0x000d, 0x0015 }, + { 0x000e, 0x001c }, + { 0x000f, 0x0021 }, + { 0x0013, 0x0110 }, + { 0x0012, 0x0093 }, + { 0x0012, 0x0094 }, + { 0x0014, 0x0062 }, + { 0x0014, 0x0063 }, + { 0x0014, 0x0064 }, + { 0x0014, 0x0065 }, + { 0x0014, 0x0066 }, + { 0x0014, 0x0067 }, + { 0x0014, 0x0068 }, + { 0x0014, 0x0069 }, + { 0x0014, 0x006a }, + { 0x0014, 0x006b }, + { 0x0014, 0x006c }, + { 0x0014, 0x006d }, + { 0x0014, 0x006e }, + { 0x000b, 0x0015 }, + { 0x000a, 0x0013 }, + { 0x000a, 0x0014 }, + { 0x000a, 0x0015 }, + { 0x000b, 0x0016 }, + { 0x000c, 0x0015 }, + { 0x000d, 0x0016 }, + { 0x000d, 0x0017 }, + { 0x000f, 0x0022 }, + { 0x0010, 0x0031 }, + { 0x0012, 0x0095 }, + { 0x0012, 0x0096 }, + { 0x0014, 0x006f }, + { 0x0013, 0x0111 }, + { 0x0014, 0x0070 }, + { 0x0014, 0x0071 }, + { 0x0014, 0x0072 }, + { 0x0014, 0x0073 }, + { 0x0014, 0x0074 }, + { 0x0014, 0x0075 }, + { 0x0014, 0x0076 }, + { 0x0014, 0x0077 }, + { 0x0014, 0x0078 }, + { 0x0014, 0x0079 }, + { 0x0014, 0x007a }, + { 0x0014, 0x007b }, + { 0x0014, 0x007c }, + { 0x000c, 0x0016 }, + { 0x000b, 0x0017 }, + { 0x000c, 0x0017 }, + { 0x000c, 0x0018 }, + { 0x000c, 0x0019 }, + { 0x000d, 0x0018 }, + { 0x000e, 0x001d }, + { 0x000f, 0x0023 }, + { 0x000f, 0x0024 }, + { 0x0011, 0x0054 }, + { 0x0012, 0x0097 }, + { 0x0014, 0x007d }, + { 0x0014, 0x007e }, + { 0x0014, 0x007f }, + { 0x0014, 0x0080 }, + { 0x0014, 0x0081 }, + { 0x0014, 0x0082 }, + { 0x0014, 0x0083 }, + { 0x0014, 0x0084 }, + { 0x0014, 0x0085 }, + { 0x0014, 0x0086 }, + { 0x0014, 0x0087 }, + { 0x0014, 0x0088 }, + { 0x0014, 0x0089 }, + { 0x0014, 0x008a }, + { 0x0014, 0x008b }, + { 0x0014, 0x008c }, + { 0x000e, 0x001e }, + { 0x000d, 0x0019 }, + { 0x000d, 0x001a }, + { 0x000d, 0x001b }, + { 0x000e, 0x001f }, + { 0x000f, 0x0025 }, + { 0x000f, 0x0026 }, + { 0x0010, 0x0032 }, + { 0x0010, 0x0033 }, + { 0x0012, 0x0098 }, + { 0x0013, 0x0112 }, + { 0x0014, 0x008d }, + { 0x0014, 0x008e }, + { 0x0014, 0x008f }, + { 0x0014, 0x0090 }, + { 0x0014, 0x0091 }, + { 0x0014, 0x0092 }, + { 0x0014, 0x0093 }, + { 0x0014, 0x0094 }, + { 0x0014, 0x0095 }, + { 0x0014, 0x0096 }, + { 0x0014, 0x0097 }, + { 0x0014, 0x0098 }, + { 0x0014, 0x0099 }, + { 0x0014, 0x009a }, + { 0x0014, 0x009b }, + { 0x0014, 0x009c }, + { 0x000f, 0x0027 }, + { 0x000f, 0x0028 }, + { 0x000f, 0x0029 }, + { 0x000f, 0x002a }, + { 0x0010, 0x0034 }, + { 0x000f, 0x002b }, + { 0x0011, 0x0055 }, + { 0x0012, 0x0099 }, + { 0x0012, 0x009a }, + { 0x0012, 0x009b }, + { 0x0014, 0x009d }, + { 0x0013, 0x0113 }, + { 0x0014, 0x009e }, + { 0x0014, 0x009f }, + { 0x0014, 0x00a0 }, + { 0x0014, 0x00a1 }, + { 0x0014, 0x00a2 }, + { 0x0014, 0x00a3 }, + { 0x0014, 0x00a4 }, + { 0x0014, 0x00a5 }, + { 0x0014, 0x00a6 }, + { 0x0014, 0x00a7 }, + { 0x0014, 0x00a8 }, + { 0x0014, 0x00a9 }, + { 0x0014, 0x00aa }, + { 0x0014, 0x00ab }, + { 0x0014, 0x00ac }, + { 0x0011, 0x0056 }, + { 0x0010, 0x0035 }, + { 0x0010, 0x0036 }, + { 0x0010, 0x0037 }, + { 0x0011, 0x0057 }, + { 0x0012, 0x009c }, + { 0x0012, 0x009d }, + { 0x0012, 0x009e }, + { 0x0014, 0x00ad }, + { 0x0014, 0x00ae }, + { 0x0014, 0x00af }, + { 0x0014, 0x00b0 }, + { 0x0014, 0x00b1 }, + { 0x0014, 0x00b2 }, + { 0x0014, 0x00b3 }, + { 0x0014, 0x00b4 }, + { 0x0014, 0x00b5 }, + { 0x0014, 0x00b6 }, + { 0x0014, 0x00b7 }, + { 0x0014, 0x00b8 }, + { 0x0014, 0x00b9 }, + { 0x0014, 0x00ba }, + { 0x0014, 0x00bb }, + { 0x0014, 0x00bc }, + { 0x0014, 0x00bd }, + { 0x0014, 0x00be }, + { 0x0014, 0x00bf }, + { 0x0012, 0x009f }, + { 0x0011, 0x0058 }, + { 0x0012, 0x00a0 }, + { 0x0014, 0x00c0 }, + { 0x0011, 0x0059 }, + { 0x0013, 0x0114 }, + { 0x0012, 0x00a1 }, + { 0x0014, 0x00c1 }, + { 0x0013, 0x0115 }, + { 0x0014, 0x00c2 }, + { 0x0014, 0x00c3 }, + { 0x0014, 0x00c4 }, + { 0x0014, 0x00c5 }, + { 0x0014, 0x00c6 }, + { 0x0014, 0x00c7 }, + { 0x0014, 0x00c8 }, + { 0x0014, 0x00c9 }, + { 0x0014, 0x00ca }, + { 0x0014, 0x00cb }, + { 0x0014, 0x00cc }, + { 0x0014, 0x00cd }, + { 0x0014, 0x00ce }, + { 0x0014, 0x00cf }, + { 0x0014, 0x00d0 }, + { 0x0014, 0x00d1 }, + { 0x0014, 0x00d2 }, + { 0x0014, 0x00d3 }, + { 0x0014, 0x00d4 }, + { 0x0014, 0x00d5 }, + { 0x0014, 0x00d6 }, + { 0x0014, 0x00d7 }, + { 0x0014, 0x00d8 }, + { 0x0014, 0x00d9 }, + { 0x0014, 0x00da }, + { 0x0014, 0x00db }, + { 0x0014, 0x00dc }, + { 0x0014, 0x00dd }, + { 0x0014, 0x00de }, + { 0x0014, 0x00df }, + { 0x0014, 0x00e0 }, + { 0x0014, 0x00e1 }, + { 0x0014, 0x00e2 }, + { 0x0014, 0x00e3 }, + { 0x0014, 0x00e4 }, + { 0x0014, 0x00e5 }, + { 0x0014, 0x00e6 }, + { 0x0014, 0x00e7 }, + { 0x0014, 0x00e8 }, + { 0x0014, 0x00e9 }, + { 0x0014, 0x00ea }, + { 0x0014, 0x00eb }, + { 0x0014, 0x00ec }, + { 0x0014, 0x00ed }, + { 0x0014, 0x00ee }, + { 0x0014, 0x00ef }, + { 0x0014, 0x00f0 }, + { 0x0014, 0x00f1 }, + { 0x0014, 0x00f2 }, + { 0x0014, 0x00f3 }, + { 0x0014, 0x00f4 }, + { 0x0014, 0x00f5 }, + { 0x0014, 0x00f6 }, + { 0x0014, 0x00f7 }, + { 0x0014, 0x00f8 }, + { 0x0014, 0x00f9 }, + { 0x0014, 0x00fa }, + { 0x0014, 0x00fb }, + { 0x0014, 0x00fc }, + { 0x0014, 0x00fd }, + { 0x0014, 0x00fe }, + { 0x0014, 0x00ff }, + { 0x0014, 0x0100 }, + { 0x0014, 0x0101 }, + { 0x0014, 0x0102 }, + { 0x0014, 0x0103 }, + { 0x0014, 0x0104 }, + { 0x0014, 0x0105 }, + { 0x0014, 0x0106 }, + { 0x0014, 0x0107 }, + { 0x0014, 0x0108 }, + { 0x0014, 0x0109 }, + { 0x0014, 0x010a }, + { 0x0014, 0x010b }, + { 0x0014, 0x010c }, + { 0x0014, 0x010d }, + { 0x0014, 0x010e }, + { 0x0014, 0x010f }, + { 0x0014, 0x0110 }, + { 0x0014, 0x0111 }, + { 0x0014, 0x0112 }, + { 0x0014, 0x0113 }, + { 0x0014, 0x0114 }, + { 0x0014, 0x0115 }, + { 0x0014, 0x0116 }, + { 0x0014, 0x0117 }, + { 0x0014, 0x0118 }, + { 0x0014, 0x0119 }, + { 0x0014, 0x011a }, + { 0x0014, 0x011b }, + { 0x0014, 0x011c }, + { 0x0014, 0x011d }, + { 0x0014, 0x011e }, + { 0x0014, 0x011f }, + { 0x0014, 0x0120 }, + { 0x0014, 0x0121 }, + { 0x0014, 0x0122 }, + { 0x0014, 0x0123 }, + { 0x0014, 0x0124 }, + { 0x0014, 0x0125 }, + { 0x0013, 0x0116 }, + { 0x0014, 0x0126 }, + { 0x0014, 0x0127 }, + { 0x0014, 0x0128 }, + { 0x0014, 0x0129 }, + { 0x0014, 0x012a }, + { 0x0014, 0x012b }, + { 0x0014, 0x012c }, + { 0x0014, 0x012d }, + { 0x0014, 0x012e }, + { 0x0014, 0x012f }, + { 0x0014, 0x0130 }, + { 0x0014, 0x0131 }, + { 0x0014, 0x0132 }, + { 0x0014, 0x0133 }, + { 0x0014, 0x0134 }, + { 0x0014, 0x0135 }, + { 0x0014, 0x0136 }, + { 0x0014, 0x0137 }, + { 0x0014, 0x0138 }, + { 0x0014, 0x0139 }, + { 0x0014, 0x013a }, + { 0x0014, 0x013b }, + { 0x0014, 0x013c }, + { 0x0014, 0x013d }, + { 0x0014, 0x013e }, + { 0x0014, 0x013f }, + { 0x0014, 0x0140 }, + { 0x0014, 0x0141 }, + { 0x0014, 0x0142 }, + { 0x0014, 0x0143 }, + { 0x0014, 0x0144 }, + { 0x0014, 0x0145 }, + { 0x0014, 0x0146 }, + { 0x0014, 0x0147 }, + { 0x0014, 0x0148 }, + { 0x0014, 0x0149 }, + { 0x0014, 0x014a }, + { 0x0014, 0x014b }, + { 0x0014, 0x014c }, + { 0x0014, 0x014d }, + { 0x0014, 0x014e }, + { 0x0014, 0x014f }, + { 0x0014, 0x0150 }, + { 0x0014, 0x0151 }, + { 0x0014, 0x0152 }, + { 0x0014, 0x0153 }, + { 0x0014, 0x0154 }, + { 0x0014, 0x0155 }, + { 0x0014, 0x0156 }, + { 0x0014, 0x0157 }, + { 0x0014, 0x0158 }, + { 0x0014, 0x0159 }, + { 0x0014, 0x015a }, + { 0x0014, 0x015b }, + { 0x0014, 0x015c }, + { 0x0014, 0x015d }, + { 0x0014, 0x015e }, + { 0x0014, 0x015f }, + { 0x0014, 0x0160 }, + { 0x0014, 0x0161 }, + { 0x0014, 0x0162 }, + { 0x0014, 0x0163 }, + { 0x0014, 0x0164 }, + { 0x0014, 0x0165 }, + { 0x0014, 0x0166 }, + { 0x0014, 0x0167 }, + { 0x0014, 0x0168 }, + { 0x0014, 0x0169 }, + { 0x0014, 0x016a }, + { 0x0014, 0x016b }, + { 0x0014, 0x016c }, + { 0x0014, 0x016d }, + { 0x0014, 0x016e }, + { 0x0014, 0x016f }, + { 0x0014, 0x0170 }, + { 0x0014, 0x0171 }, + { 0x0014, 0x0172 }, + { 0x0014, 0x0173 }, + { 0x0014, 0x0174 }, + { 0x0014, 0x0175 }, + { 0x0014, 0x0176 }, + { 0x0014, 0x0177 }, + { 0x0014, 0x0178 }, + { 0x0014, 0x0179 }, + { 0x0014, 0x017a }, + { 0x0014, 0x017b }, + { 0x0014, 0x017c }, + { 0x0014, 0x017d }, + { 0x0014, 0x017e }, + { 0x0014, 0x017f }, + { 0x0014, 0x0180 }, + { 0x0014, 0x0181 }, + { 0x0014, 0x0182 }, + { 0x0014, 0x0183 }, + { 0x0014, 0x0184 }, + { 0x0014, 0x0185 }, + { 0x0014, 0x0186 }, + { 0x0014, 0x0187 }, + { 0x0014, 0x0188 }, + { 0x0014, 0x0189 }, + { 0x0014, 0x018a }, + { 0x0014, 0x018b }, + { 0x0014, 0x018c }, + { 0x0014, 0x018d }, + { 0x0014, 0x018e }, + { 0x0014, 0x018f }, + { 0x0014, 0x0190 }, + { 0x0014, 0x0191 }, + { 0x0014, 0x0192 }, + { 0x0014, 0x0193 }, + { 0x0014, 0x0194 }, + { 0x0014, 0x0195 }, + { 0x0014, 0x0196 }, + { 0x0014, 0x0197 }, + { 0x0014, 0x0198 }, + { 0x0014, 0x0199 }, + { 0x0014, 0x019a }, + { 0x0014, 0x019b }, + { 0x0014, 0x019c }, + { 0x0014, 0x019d }, + { 0x0014, 0x019e }, + { 0x0014, 0x019f }, + { 0x0014, 0x01a0 }, + { 0x0014, 0x01a1 }, + { 0x0014, 0x01a2 }, + { 0x0014, 0x01a3 }, + { 0x0014, 0x01a4 }, + { 0x0014, 0x01a5 }, + { 0x0014, 0x01a6 }, + { 0x0014, 0x01a7 }, + { 0x0014, 0x01a8 }, + { 0x0014, 0x01a9 }, + { 0x0014, 0x01aa }, + { 0x0014, 0x01ab }, + { 0x0014, 0x01ac }, + { 0x0014, 0x01ad }, + { 0x0014, 0x01ae }, + { 0x0014, 0x01af }, + { 0x0014, 0x01b0 }, + { 0x0014, 0x01b1 }, + { 0x0014, 0x01b2 }, + { 0x0014, 0x01b3 }, + { 0x0014, 0x01b4 }, + { 0x0014, 0x01b5 }, + { 0x0014, 0x01b6 }, + { 0x0014, 0x01b7 }, + { 0x0014, 0x01b8 }, + { 0x0014, 0x01b9 }, + { 0x0014, 0x01ba }, + { 0x0014, 0x01bb }, + { 0x0014, 0x01bc }, + { 0x0014, 0x01bd }, + { 0x0014, 0x01be }, + { 0x0014, 0x01bf }, + { 0x0014, 0x01c0 }, + { 0x0014, 0x01c1 }, + { 0x0014, 0x01c2 }, + { 0x0014, 0x01c3 }, + { 0x0014, 0x01c4 }, + { 0x0014, 0x01c5 }, + { 0x0014, 0x01c6 }, + { 0x0014, 0x01c7 }, + { 0x0014, 0x01c8 }, + { 0x0014, 0x01c9 }, + { 0x0014, 0x01ca }, + { 0x0014, 0x01cb }, + { 0x0014, 0x01cc }, + { 0x0014, 0x01cd }, + { 0x0014, 0x01ce }, + { 0x0014, 0x01cf }, + { 0x0014, 0x01d0 }, + { 0x0014, 0x01d1 }, + { 0x0014, 0x01d2 }, + { 0x0014, 0x01d3 }, + { 0x0014, 0x01d4 }, + { 0x0014, 0x01d5 }, + { 0x0014, 0x01d6 }, + { 0x0014, 0x01d7 }, + { 0x0014, 0x01d8 }, + { 0x0014, 0x01d9 }, + { 0x0014, 0x01da }, + { 0x0014, 0x01db }, + { 0x0014, 0x01dc }, + { 0x0014, 0x01dd }, + { 0x0014, 0x01de }, + { 0x0014, 0x01df }, + { 0x0014, 0x01e0 }, + { 0x0014, 0x01e1 }, + { 0x0014, 0x01e2 }, + { 0x0014, 0x01e3 }, + { 0x0014, 0x01e4 }, + { 0x0014, 0x01e5 }, + { 0x0014, 0x01e6 }, + { 0x0014, 0x01e7 }, + { 0x0014, 0x01e8 }, + { 0x0014, 0x01e9 }, + { 0x0014, 0x01ea }, + { 0x0014, 0x01eb }, + { 0x0014, 0x01ec }, + { 0x0014, 0x01ed }, + { 0x0014, 0x01ee }, + { 0x0014, 0x01ef }, + { 0x0014, 0x01f0 }, + { 0x0014, 0x01f1 }, + { 0x0014, 0x01f2 }, + { 0x0014, 0x01f3 }, + { 0x0014, 0x01f4 }, + { 0x0014, 0x01f5 }, + { 0x0014, 0x01f6 }, + { 0x0014, 0x01f7 }, + { 0x0014, 0x01f8 }, + { 0x0014, 0x01f9 }, + { 0x0014, 0x01fa }, + { 0x0014, 0x01fb }, + { 0x0014, 0x01fc }, + { 0x0014, 0x01fd }, + { 0x0014, 0x01fe }, + { 0x0014, 0x01ff }, + { 0x0014, 0x0200 }, + { 0x0014, 0x0201 }, + { 0x0014, 0x0202 }, + { 0x0014, 0x0203 }, + { 0x0014, 0x0204 }, + { 0x0014, 0x0205 }, + { 0x0014, 0x0206 }, + { 0x0014, 0x0207 }, + { 0x0014, 0x0208 }, + { 0x0014, 0x0209 }, + { 0x0014, 0x020a }, + { 0x0014, 0x020b }, + { 0x0014, 0x020c }, + { 0x0014, 0x020d }, + { 0x0014, 0x020e }, + { 0x0014, 0x020f }, + { 0x0014, 0x0210 }, + { 0x0014, 0x0211 }, + { 0x0014, 0x0212 }, + { 0x0014, 0x0213 }, + { 0x0014, 0x0214 }, + { 0x0014, 0x0215 }, + { 0x0013, 0x0117 }, + + }; + + +const uint16_t c_aauiLCLDHuffEnc17[729][2] = + { + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0006, 0x0014 }, + { 0x0006, 0x0015 }, + { 0x0007, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0008, 0x000e }, + { 0x0008, 0x000f }, + { 0x0009, 0x000f }, + { 0x000a, 0x000f }, + { 0x000c, 0x0011 }, + { 0x000d, 0x0014 }, + { 0x000e, 0x0017 }, + { 0x0010, 0x002d }, + { 0x0011, 0x004c }, + { 0x0012, 0x008a }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0014, 0x0006 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0014, 0x0009 }, + { 0x0006, 0x0016 }, + { 0x0005, 0x0018 }, + { 0x0005, 0x0019 }, + { 0x0005, 0x001a }, + { 0x0006, 0x0017 }, + { 0x0006, 0x0018 }, + { 0x0006, 0x0019 }, + { 0x0007, 0x0012 }, + { 0x0007, 0x0013 }, + { 0x0008, 0x0010 }, + { 0x000a, 0x0010 }, + { 0x000b, 0x0011 }, + { 0x000c, 0x0012 }, + { 0x000e, 0x0018 }, + { 0x000f, 0x0020 }, + { 0x0011, 0x004d }, + { 0x0013, 0x00e4 }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0014, 0x000c }, + { 0x0014, 0x000d }, + { 0x0014, 0x000e }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0014, 0x0013 }, + { 0x0006, 0x001a }, + { 0x0005, 0x001b }, + { 0x0005, 0x001c }, + { 0x0005, 0x001d }, + { 0x0006, 0x001b }, + { 0x0006, 0x001c }, + { 0x0006, 0x001d }, + { 0x0007, 0x0014 }, + { 0x0008, 0x0011 }, + { 0x0009, 0x0010 }, + { 0x000a, 0x0011 }, + { 0x000b, 0x0012 }, + { 0x000c, 0x0013 }, + { 0x000e, 0x0019 }, + { 0x000f, 0x0021 }, + { 0x0010, 0x002e }, + { 0x0013, 0x00e5 }, + { 0x0013, 0x00e6 }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + { 0x0014, 0x001a }, + { 0x0014, 0x001b }, + { 0x0014, 0x001c }, + { 0x0006, 0x001e }, + { 0x0005, 0x001e }, + { 0x0005, 0x001f }, + { 0x0006, 0x001f }, + { 0x0006, 0x0020 }, + { 0x0006, 0x0021 }, + { 0x0006, 0x0022 }, + { 0x0007, 0x0015 }, + { 0x0008, 0x0012 }, + { 0x0009, 0x0011 }, + { 0x000a, 0x0012 }, + { 0x000b, 0x0013 }, + { 0x000c, 0x0014 }, + { 0x000e, 0x001a }, + { 0x000f, 0x0022 }, + { 0x0010, 0x002f }, + { 0x0013, 0x00e7 }, + { 0x0013, 0x00e8 }, + { 0x0014, 0x001d }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0014, 0x0020 }, + { 0x0014, 0x0021 }, + { 0x0014, 0x0022 }, + { 0x0014, 0x0023 }, + { 0x0014, 0x0024 }, + { 0x0014, 0x0025 }, + { 0x0006, 0x0023 }, + { 0x0006, 0x0024 }, + { 0x0006, 0x0025 }, + { 0x0006, 0x0026 }, + { 0x0006, 0x0027 }, + { 0x0006, 0x0028 }, + { 0x0007, 0x0016 }, + { 0x0007, 0x0017 }, + { 0x0008, 0x0013 }, + { 0x0009, 0x0012 }, + { 0x000a, 0x0013 }, + { 0x000c, 0x0015 }, + { 0x000d, 0x0015 }, + { 0x000f, 0x0023 }, + { 0x0010, 0x0030 }, + { 0x0011, 0x004e }, + { 0x0014, 0x0026 }, + { 0x0014, 0x0027 }, + { 0x0014, 0x0028 }, + { 0x0014, 0x0029 }, + { 0x0014, 0x002a }, + { 0x0014, 0x002b }, + { 0x0014, 0x002c }, + { 0x0014, 0x002d }, + { 0x0014, 0x002e }, + { 0x0014, 0x002f }, + { 0x0014, 0x0030 }, + { 0x0007, 0x0018 }, + { 0x0006, 0x0029 }, + { 0x0006, 0x002a }, + { 0x0006, 0x002b }, + { 0x0006, 0x002c }, + { 0x0007, 0x0019 }, + { 0x0007, 0x001a }, + { 0x0008, 0x0014 }, + { 0x0009, 0x0013 }, + { 0x000a, 0x0014 }, + { 0x000b, 0x0014 }, + { 0x000c, 0x0016 }, + { 0x000d, 0x0016 }, + { 0x000f, 0x0024 }, + { 0x0010, 0x0031 }, + { 0x0011, 0x004f }, + { 0x0014, 0x0031 }, + { 0x0014, 0x0032 }, + { 0x0014, 0x0033 }, + { 0x0014, 0x0034 }, + { 0x0014, 0x0035 }, + { 0x0014, 0x0036 }, + { 0x0014, 0x0037 }, + { 0x0014, 0x0038 }, + { 0x0014, 0x0039 }, + { 0x0014, 0x003a }, + { 0x0014, 0x003b }, + { 0x0007, 0x001b }, + { 0x0006, 0x002d }, + { 0x0006, 0x002e }, + { 0x0006, 0x002f }, + { 0x0007, 0x001c }, + { 0x0007, 0x001d }, + { 0x0008, 0x0015 }, + { 0x0009, 0x0014 }, + { 0x000a, 0x0015 }, + { 0x000a, 0x0016 }, + { 0x000c, 0x0017 }, + { 0x000d, 0x0017 }, + { 0x000e, 0x001b }, + { 0x000f, 0x0025 }, + { 0x0011, 0x0050 }, + { 0x0011, 0x0051 }, + { 0x0014, 0x003c }, + { 0x0014, 0x003d }, + { 0x0014, 0x003e }, + { 0x0014, 0x003f }, + { 0x0014, 0x0040 }, + { 0x0014, 0x0041 }, + { 0x0014, 0x0042 }, + { 0x0014, 0x0043 }, + { 0x0014, 0x0044 }, + { 0x0014, 0x0045 }, + { 0x0014, 0x0046 }, + { 0x0008, 0x0016 }, + { 0x0007, 0x001e }, + { 0x0007, 0x001f }, + { 0x0007, 0x0020 }, + { 0x0007, 0x0021 }, + { 0x0008, 0x0017 }, + { 0x0008, 0x0018 }, + { 0x0009, 0x0015 }, + { 0x000a, 0x0017 }, + { 0x000b, 0x0015 }, + { 0x000c, 0x0018 }, + { 0x000e, 0x001c }, + { 0x000e, 0x001d }, + { 0x0010, 0x0032 }, + { 0x0012, 0x008b }, + { 0x0012, 0x008c }, + { 0x0014, 0x0047 }, + { 0x0014, 0x0048 }, + { 0x0014, 0x0049 }, + { 0x0014, 0x004a }, + { 0x0014, 0x004b }, + { 0x0014, 0x004c }, + { 0x0014, 0x004d }, + { 0x0014, 0x004e }, + { 0x0014, 0x004f }, + { 0x0014, 0x0050 }, + { 0x0014, 0x0051 }, + { 0x0008, 0x0019 }, + { 0x0007, 0x0022 }, + { 0x0007, 0x0023 }, + { 0x0008, 0x001a }, + { 0x0008, 0x001b }, + { 0x0009, 0x0016 }, + { 0x0009, 0x0017 }, + { 0x000a, 0x0018 }, + { 0x000b, 0x0016 }, + { 0x000c, 0x0019 }, + { 0x000d, 0x0018 }, + { 0x000e, 0x001e }, + { 0x0010, 0x0033 }, + { 0x0011, 0x0052 }, + { 0x0014, 0x0052 }, + { 0x0013, 0x00e9 }, + { 0x0014, 0x0053 }, + { 0x0014, 0x0054 }, + { 0x0014, 0x0055 }, + { 0x0014, 0x0056 }, + { 0x0014, 0x0057 }, + { 0x0014, 0x0058 }, + { 0x0014, 0x0059 }, + { 0x0014, 0x005a }, + { 0x0014, 0x005b }, + { 0x0014, 0x005c }, + { 0x0014, 0x005d }, + { 0x0009, 0x0018 }, + { 0x0008, 0x001c }, + { 0x0008, 0x001d }, + { 0x0009, 0x0019 }, + { 0x0009, 0x001a }, + { 0x000a, 0x0019 }, + { 0x000a, 0x001a }, + { 0x000b, 0x0017 }, + { 0x000c, 0x001a }, + { 0x000d, 0x0019 }, + { 0x000e, 0x001f }, + { 0x000f, 0x0026 }, + { 0x0010, 0x0034 }, + { 0x0012, 0x008d }, + { 0x0013, 0x00ea }, + { 0x0014, 0x005e }, + { 0x0014, 0x005f }, + { 0x0014, 0x0060 }, + { 0x0014, 0x0061 }, + { 0x0014, 0x0062 }, + { 0x0014, 0x0063 }, + { 0x0014, 0x0064 }, + { 0x0014, 0x0065 }, + { 0x0014, 0x0066 }, + { 0x0014, 0x0067 }, + { 0x0014, 0x0068 }, + { 0x0014, 0x0069 }, + { 0x000b, 0x0018 }, + { 0x0009, 0x001b }, + { 0x000a, 0x001b }, + { 0x000a, 0x001c }, + { 0x000a, 0x001d }, + { 0x000b, 0x0019 }, + { 0x000b, 0x001a }, + { 0x000c, 0x001b }, + { 0x000d, 0x001a }, + { 0x000e, 0x0020 }, + { 0x000f, 0x0027 }, + { 0x0012, 0x008e }, + { 0x0011, 0x0053 }, + { 0x0013, 0x00eb }, + { 0x0014, 0x006a }, + { 0x0014, 0x006b }, + { 0x0014, 0x006c }, + { 0x0014, 0x006d }, + { 0x0014, 0x006e }, + { 0x0014, 0x006f }, + { 0x0014, 0x0070 }, + { 0x0014, 0x0071 }, + { 0x0014, 0x0072 }, + { 0x0014, 0x0073 }, + { 0x0014, 0x0074 }, + { 0x0014, 0x0075 }, + { 0x0014, 0x0076 }, + { 0x000c, 0x001c }, + { 0x000b, 0x001b }, + { 0x000b, 0x001c }, + { 0x000b, 0x001d }, + { 0x000c, 0x001d }, + { 0x000c, 0x001e }, + { 0x000d, 0x001b }, + { 0x000d, 0x001c }, + { 0x000e, 0x0021 }, + { 0x0010, 0x0035 }, + { 0x0010, 0x0036 }, + { 0x0011, 0x0054 }, + { 0x0013, 0x00ec }, + { 0x0014, 0x0077 }, + { 0x0014, 0x0078 }, + { 0x0014, 0x0079 }, + { 0x0014, 0x007a }, + { 0x0014, 0x007b }, + { 0x0014, 0x007c }, + { 0x0014, 0x007d }, + { 0x0014, 0x007e }, + { 0x0014, 0x007f }, + { 0x0014, 0x0080 }, + { 0x0014, 0x0081 }, + { 0x0014, 0x0082 }, + { 0x0014, 0x0083 }, + { 0x0014, 0x0084 }, + { 0x000d, 0x001d }, + { 0x000c, 0x001f }, + { 0x000c, 0x0020 }, + { 0x000c, 0x0021 }, + { 0x000d, 0x001e }, + { 0x000d, 0x001f }, + { 0x000e, 0x0022 }, + { 0x000f, 0x0028 }, + { 0x0010, 0x0037 }, + { 0x0010, 0x0038 }, + { 0x0010, 0x0039 }, + { 0x0012, 0x008f }, + { 0x0013, 0x00ed }, + { 0x0014, 0x0085 }, + { 0x0014, 0x0086 }, + { 0x0014, 0x0087 }, + { 0x0014, 0x0088 }, + { 0x0014, 0x0089 }, + { 0x0014, 0x008a }, + { 0x0014, 0x008b }, + { 0x0014, 0x008c }, + { 0x0014, 0x008d }, + { 0x0014, 0x008e }, + { 0x0014, 0x008f }, + { 0x0014, 0x0090 }, + { 0x0014, 0x0091 }, + { 0x0014, 0x0092 }, + { 0x000e, 0x0023 }, + { 0x000d, 0x0020 }, + { 0x000d, 0x0021 }, + { 0x000e, 0x0024 }, + { 0x000e, 0x0025 }, + { 0x000e, 0x0026 }, + { 0x000f, 0x0029 }, + { 0x0010, 0x003a }, + { 0x0010, 0x003b }, + { 0x0012, 0x0090 }, + { 0x0014, 0x0093 }, + { 0x0014, 0x0094 }, + { 0x0014, 0x0095 }, + { 0x0014, 0x0096 }, + { 0x0014, 0x0097 }, + { 0x0014, 0x0098 }, + { 0x0014, 0x0099 }, + { 0x0014, 0x009a }, + { 0x0014, 0x009b }, + { 0x0014, 0x009c }, + { 0x0014, 0x009d }, + { 0x0014, 0x009e }, + { 0x0014, 0x009f }, + { 0x0014, 0x00a0 }, + { 0x0014, 0x00a1 }, + { 0x0014, 0x00a2 }, + { 0x0014, 0x00a3 }, + { 0x000f, 0x002a }, + { 0x000e, 0x0027 }, + { 0x000f, 0x002b }, + { 0x000f, 0x002c }, + { 0x000f, 0x002d }, + { 0x0010, 0x003c }, + { 0x0010, 0x003d }, + { 0x0011, 0x0055 }, + { 0x0011, 0x0056 }, + { 0x0014, 0x00a4 }, + { 0x0014, 0x00a5 }, + { 0x0014, 0x00a6 }, + { 0x0014, 0x00a7 }, + { 0x0014, 0x00a8 }, + { 0x0014, 0x00a9 }, + { 0x0014, 0x00aa }, + { 0x0014, 0x00ab }, + { 0x0014, 0x00ac }, + { 0x0014, 0x00ad }, + { 0x0014, 0x00ae }, + { 0x0014, 0x00af }, + { 0x0014, 0x00b0 }, + { 0x0014, 0x00b1 }, + { 0x0014, 0x00b2 }, + { 0x0014, 0x00b3 }, + { 0x0014, 0x00b4 }, + { 0x0014, 0x00b5 }, + { 0x0012, 0x0091 }, + { 0x0010, 0x003e }, + { 0x0010, 0x003f }, + { 0x0011, 0x0057 }, + { 0x0011, 0x0058 }, + { 0x0011, 0x0059 }, + { 0x0012, 0x0092 }, + { 0x0013, 0x00ee }, + { 0x0013, 0x00ef }, + { 0x0012, 0x0093 }, + { 0x0014, 0x00b6 }, + { 0x0014, 0x00b7 }, + { 0x0014, 0x00b8 }, + { 0x0014, 0x00b9 }, + { 0x0014, 0x00ba }, + { 0x0014, 0x00bb }, + { 0x0014, 0x00bc }, + { 0x0014, 0x00bd }, + { 0x0014, 0x00be }, + { 0x0014, 0x00bf }, + { 0x0014, 0x00c0 }, + { 0x0014, 0x00c1 }, + { 0x0014, 0x00c2 }, + { 0x0014, 0x00c3 }, + { 0x0014, 0x00c4 }, + { 0x0014, 0x00c5 }, + { 0x0014, 0x00c6 }, + { 0x0013, 0x00f0 }, + { 0x0012, 0x0094 }, + { 0x0012, 0x0095 }, + { 0x0012, 0x0096 }, + { 0x0014, 0x00c7 }, + { 0x0014, 0x00c8 }, + { 0x0014, 0x00c9 }, + { 0x0014, 0x00ca }, + { 0x0014, 0x00cb }, + { 0x0014, 0x00cc }, + { 0x0014, 0x00cd }, + { 0x0014, 0x00ce }, + { 0x0014, 0x00cf }, + { 0x0014, 0x00d0 }, + { 0x0014, 0x00d1 }, + { 0x0014, 0x00d2 }, + { 0x0014, 0x00d3 }, + { 0x0014, 0x00d4 }, + { 0x0014, 0x00d5 }, + { 0x0014, 0x00d6 }, + { 0x0014, 0x00d7 }, + { 0x0014, 0x00d8 }, + { 0x0014, 0x00d9 }, + { 0x0014, 0x00da }, + { 0x0014, 0x00db }, + { 0x0014, 0x00dc }, + { 0x0014, 0x00dd }, + { 0x0014, 0x00de }, + { 0x0012, 0x0097 }, + { 0x0014, 0x00df }, + { 0x0014, 0x00e0 }, + { 0x0014, 0x00e1 }, + { 0x0014, 0x00e2 }, + { 0x0014, 0x00e3 }, + { 0x0014, 0x00e4 }, + { 0x0014, 0x00e5 }, + { 0x0014, 0x00e6 }, + { 0x0014, 0x00e7 }, + { 0x0014, 0x00e8 }, + { 0x0014, 0x00e9 }, + { 0x0014, 0x00ea }, + { 0x0014, 0x00eb }, + { 0x0014, 0x00ec }, + { 0x0014, 0x00ed }, + { 0x0014, 0x00ee }, + { 0x0014, 0x00ef }, + { 0x0014, 0x00f0 }, + { 0x0014, 0x00f1 }, + { 0x0014, 0x00f2 }, + { 0x0014, 0x00f3 }, + { 0x0014, 0x00f4 }, + { 0x0014, 0x00f5 }, + { 0x0014, 0x00f6 }, + { 0x0014, 0x00f7 }, + { 0x0014, 0x00f8 }, + { 0x0014, 0x00f9 }, + { 0x0014, 0x00fa }, + { 0x0014, 0x00fb }, + { 0x0014, 0x00fc }, + { 0x0014, 0x00fd }, + { 0x0014, 0x00fe }, + { 0x0014, 0x00ff }, + { 0x0014, 0x0100 }, + { 0x0014, 0x0101 }, + { 0x0014, 0x0102 }, + { 0x0014, 0x0103 }, + { 0x0014, 0x0104 }, + { 0x0014, 0x0105 }, + { 0x0014, 0x0106 }, + { 0x0014, 0x0107 }, + { 0x0014, 0x0108 }, + { 0x0014, 0x0109 }, + { 0x0014, 0x010a }, + { 0x0014, 0x010b }, + { 0x0014, 0x010c }, + { 0x0014, 0x010d }, + { 0x0014, 0x010e }, + { 0x0014, 0x010f }, + { 0x0014, 0x0110 }, + { 0x0014, 0x0111 }, + { 0x0014, 0x0112 }, + { 0x0014, 0x0113 }, + { 0x0014, 0x0114 }, + { 0x0014, 0x0115 }, + { 0x0014, 0x0116 }, + { 0x0014, 0x0117 }, + { 0x0014, 0x0118 }, + { 0x0014, 0x0119 }, + { 0x0014, 0x011a }, + { 0x0014, 0x011b }, + { 0x0014, 0x011c }, + { 0x0014, 0x011d }, + { 0x0014, 0x011e }, + { 0x0014, 0x011f }, + { 0x0014, 0x0120 }, + { 0x0014, 0x0121 }, + { 0x0014, 0x0122 }, + { 0x0014, 0x0123 }, + { 0x0014, 0x0124 }, + { 0x0014, 0x0125 }, + { 0x0014, 0x0126 }, + { 0x0014, 0x0127 }, + { 0x0014, 0x0128 }, + { 0x0014, 0x0129 }, + { 0x0014, 0x012a }, + { 0x0014, 0x012b }, + { 0x0014, 0x012c }, + { 0x0014, 0x012d }, + { 0x0014, 0x012e }, + { 0x0014, 0x012f }, + { 0x0014, 0x0130 }, + { 0x0014, 0x0131 }, + { 0x0014, 0x0132 }, + { 0x0014, 0x0133 }, + { 0x0014, 0x0134 }, + { 0x0014, 0x0135 }, + { 0x0014, 0x0136 }, + { 0x0014, 0x0137 }, + { 0x0014, 0x0138 }, + { 0x0014, 0x0139 }, + { 0x0014, 0x013a }, + { 0x0014, 0x013b }, + { 0x0014, 0x013c }, + { 0x0014, 0x013d }, + { 0x0014, 0x013e }, + { 0x0014, 0x013f }, + { 0x0014, 0x0140 }, + { 0x0014, 0x0141 }, + { 0x0014, 0x0142 }, + { 0x0014, 0x0143 }, + { 0x0014, 0x0144 }, + { 0x0014, 0x0145 }, + { 0x0014, 0x0146 }, + { 0x0014, 0x0147 }, + { 0x0014, 0x0148 }, + { 0x0014, 0x0149 }, + { 0x0014, 0x014a }, + { 0x0014, 0x014b }, + { 0x0014, 0x014c }, + { 0x0014, 0x014d }, + { 0x0014, 0x014e }, + { 0x0014, 0x014f }, + { 0x0014, 0x0150 }, + { 0x0014, 0x0151 }, + { 0x0014, 0x0152 }, + { 0x0014, 0x0153 }, + { 0x0014, 0x0154 }, + { 0x0014, 0x0155 }, + { 0x0014, 0x0156 }, + { 0x0014, 0x0157 }, + { 0x0014, 0x0158 }, + { 0x0014, 0x0159 }, + { 0x0014, 0x015a }, + { 0x0014, 0x015b }, + { 0x0014, 0x015c }, + { 0x0014, 0x015d }, + { 0x0014, 0x015e }, + { 0x0014, 0x015f }, + { 0x0014, 0x0160 }, + { 0x0014, 0x0161 }, + { 0x0014, 0x0162 }, + { 0x0014, 0x0163 }, + { 0x0014, 0x0164 }, + { 0x0014, 0x0165 }, + { 0x0014, 0x0166 }, + { 0x0014, 0x0167 }, + { 0x0014, 0x0168 }, + { 0x0014, 0x0169 }, + { 0x0014, 0x016a }, + { 0x0014, 0x016b }, + { 0x0014, 0x016c }, + { 0x0014, 0x016d }, + { 0x0014, 0x016e }, + { 0x0014, 0x016f }, + { 0x0014, 0x0170 }, + { 0x0014, 0x0171 }, + { 0x0014, 0x0172 }, + { 0x0014, 0x0173 }, + { 0x0014, 0x0174 }, + { 0x0014, 0x0175 }, + { 0x0014, 0x0176 }, + { 0x0014, 0x0177 }, + { 0x0014, 0x0178 }, + { 0x0014, 0x0179 }, + { 0x0014, 0x017a }, + { 0x0014, 0x017b }, + { 0x0014, 0x017c }, + { 0x0014, 0x017d }, + { 0x0014, 0x017e }, + { 0x0014, 0x017f }, + { 0x0014, 0x0180 }, + { 0x0014, 0x0181 }, + { 0x0014, 0x0182 }, + { 0x0014, 0x0183 }, + { 0x0014, 0x0184 }, + { 0x0014, 0x0185 }, + { 0x0014, 0x0186 }, + { 0x0014, 0x0187 }, + { 0x0014, 0x0188 }, + { 0x0014, 0x0189 }, + { 0x0014, 0x018a }, + { 0x0014, 0x018b }, + { 0x0014, 0x018c }, + { 0x0014, 0x018d }, + { 0x0014, 0x018e }, + { 0x0014, 0x018f }, + { 0x0014, 0x0190 }, + { 0x0014, 0x0191 }, + { 0x0014, 0x0192 }, + { 0x0014, 0x0193 }, + { 0x0014, 0x0194 }, + { 0x0014, 0x0195 }, + { 0x0014, 0x0196 }, + { 0x0014, 0x0197 }, + { 0x0014, 0x0198 }, + { 0x0014, 0x0199 }, + { 0x0014, 0x019a }, + { 0x0014, 0x019b }, + { 0x0014, 0x019c }, + { 0x0014, 0x019d }, + { 0x0014, 0x019e }, + { 0x0014, 0x019f }, + { 0x0014, 0x01a0 }, + { 0x0014, 0x01a1 }, + { 0x0014, 0x01a2 }, + { 0x0014, 0x01a3 }, + { 0x0014, 0x01a4 }, + { 0x0014, 0x01a5 }, + { 0x0014, 0x01a6 }, + { 0x0014, 0x01a7 }, + { 0x0014, 0x01a8 }, + { 0x0014, 0x01a9 }, + { 0x0014, 0x01aa }, + { 0x0014, 0x01ab }, + { 0x0014, 0x01ac }, + { 0x0014, 0x01ad }, + { 0x0014, 0x01ae }, + { 0x0014, 0x01af }, + { 0x0014, 0x01b0 }, + { 0x0014, 0x01b1 }, + { 0x0014, 0x01b2 }, + { 0x0014, 0x01b3 }, + { 0x0014, 0x01b4 }, + { 0x0014, 0x01b5 }, + { 0x0014, 0x01b6 }, + { 0x0014, 0x01b7 }, + { 0x0014, 0x01b8 }, + { 0x0014, 0x01b9 }, + { 0x0014, 0x01ba }, + { 0x0014, 0x01bb }, + { 0x0014, 0x01bc }, + { 0x0014, 0x01bd }, + { 0x0014, 0x01be }, + { 0x0014, 0x01bf }, + { 0x0014, 0x01c0 }, + { 0x0014, 0x01c1 }, + { 0x0014, 0x01c2 }, + { 0x0014, 0x01c3 }, + { 0x0014, 0x01c4 }, + { 0x0014, 0x01c5 }, + { 0x0014, 0x01c6 }, + { 0x0014, 0x01c7 }, + { 0x0013, 0x00f1 }, + { 0x0013, 0x00f2 }, + { 0x0013, 0x00f3 }, + { 0x0013, 0x00f4 }, + { 0x0013, 0x00f5 }, + { 0x0013, 0x00f6 }, + { 0x0013, 0x00f7 }, + { 0x0013, 0x00f8 }, + { 0x0013, 0x00f9 }, + { 0x0013, 0x00fa }, + { 0x0013, 0x00fb }, + { 0x0013, 0x00fc }, + { 0x0013, 0x00fd }, + { 0x0013, 0x00fe }, + { 0x0013, 0x00ff }, + { 0x0013, 0x0100 }, + { 0x0013, 0x0101 }, + { 0x0013, 0x0102 }, + { 0x0013, 0x0103 }, + { 0x0013, 0x0104 }, + { 0x0013, 0x0105 }, + { 0x0013, 0x0106 }, + { 0x0013, 0x0107 }, + { 0x0013, 0x0108 }, + { 0x0013, 0x0109 }, + { 0x0013, 0x010a }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0013, 0x010f }, + { 0x0013, 0x0110 }, + { 0x0013, 0x0111 }, + { 0x0013, 0x0112 }, + { 0x0013, 0x0113 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc18[28][2] = + { + { 0x0004, 0x0001 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0002 }, + { 0x0004, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x000f, 0x0001 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + + }; + + +const uint16_t c_aauiLCLDHuffEnc19[29][2] = + { + { 0x0004, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0003 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0005, 0x0001 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0006, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x000f, 0x0001 }, + { 0x0010, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0012, 0x0003 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc20[32][2] = + { + { 0x0004, 0x0002 }, + { 0x0003, 0x0005 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0003 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0006, 0x0001 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0007, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x000f, 0x0001 }, + { 0x0010, 0x0001 }, + { 0x0011, 0x0001 }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + }; + +const uint16_t c_aauiLCLDHuffEnc21[37][2] = + { + { 0x0005, 0x0002 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0003 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0005, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0007, 0x0002 }, + { 0x0007, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0009, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x000f, 0x0001 }, + { 0x0010, 0x0001 }, + { 0x0011, 0x0001 }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc22[39][2] = + { + { 0x0005, 0x0002 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0004, 0x000c }, + { 0x0004, 0x000d }, + { 0x0004, 0x000e }, + { 0x0004, 0x000f }, + { 0x0005, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0007, 0x0002 }, + { 0x0007, 0x0003 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000a, 0x0001 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000c, 0x0001 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000e, 0x0001 }, + { 0x000e, 0x0002 }, + { 0x000f, 0x0001 }, + { 0x000e, 0x0003 }, + { 0x0011, 0x0000 }, + { 0x0010, 0x0001 }, + { 0x0011, 0x0001 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc23[46][2] = + { + { 0x0005, 0x0003 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0004, 0x000c }, + { 0x0004, 0x000d }, + { 0x0004, 0x000e }, + { 0x0004, 0x000f }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0006, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0002 }, + { 0x0007, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000d, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x000e, 0x0001 }, + { 0x000e, 0x0002 }, + { 0x000e, 0x0003 }, + { 0x000f, 0x0001 }, + { 0x0010, 0x0001 }, + { 0x0012, 0x0000 }, + { 0x0012, 0x0001 }, + { 0x0011, 0x0001 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc24[55][2] = + { + { 0x0005, 0x0004 }, + { 0x0004, 0x0009 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0004, 0x000c }, + { 0x0004, 0x000d }, + { 0x0004, 0x000e }, + { 0x0004, 0x000f }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0005, 0x0010 }, + { 0x0005, 0x0011 }, + { 0x0006, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0007, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0003 }, + { 0x000d, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000e, 0x0002 }, + { 0x000e, 0x0003 }, + { 0x000f, 0x0001 }, + { 0x000f, 0x0002 }, + { 0x000f, 0x0003 }, + { 0x0010, 0x0001 }, + { 0x0011, 0x0001 }, + { 0x0013, 0x0000 }, + { 0x0012, 0x0001 }, + { 0x0013, 0x0001 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc25[65][2] = + { + { 0x0005, 0x0005 }, + { 0x0004, 0x000c }, + { 0x0004, 0x000d }, + { 0x0004, 0x000e }, + { 0x0005, 0x0006 }, + { 0x0004, 0x000f }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0005, 0x0010 }, + { 0x0005, 0x0011 }, + { 0x0005, 0x0012 }, + { 0x0005, 0x0013 }, + { 0x0005, 0x0014 }, + { 0x0005, 0x0015 }, + { 0x0005, 0x0016 }, + { 0x0005, 0x0017 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0007, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0009, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000a, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000b, 0x0003 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000d, 0x0003 }, + { 0x000e, 0x0003 }, + { 0x000e, 0x0004 }, + { 0x000f, 0x0003 }, + { 0x000e, 0x0005 }, + { 0x000f, 0x0004 }, + { 0x0010, 0x0001 }, + { 0x000f, 0x0005 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0010, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x0011, 0x0001 }, + { 0x0012, 0x0000 }, + { 0x0012, 0x0001 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc26[77][2] = + { + { 0x0006, 0x0004 }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0005, 0x0010 }, + { 0x0005, 0x0011 }, + { 0x0005, 0x0012 }, + { 0x0005, 0x0013 }, + { 0x0005, 0x0014 }, + { 0x0005, 0x0015 }, + { 0x0005, 0x0016 }, + { 0x0005, 0x0017 }, + { 0x0005, 0x0018 }, + { 0x0005, 0x0019 }, + { 0x0005, 0x001a }, + { 0x0005, 0x001b }, + { 0x0005, 0x001c }, + { 0x0005, 0x001d }, + { 0x0005, 0x001e }, + { 0x0005, 0x001f }, + { 0x0006, 0x0005 }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0009, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x000a, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000c, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x000e, 0x0002 }, + { 0x000d, 0x0005 }, + { 0x000e, 0x0003 }, + { 0x000e, 0x0004 }, + { 0x000f, 0x0003 }, + { 0x000e, 0x0005 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0010, 0x0004 }, + { 0x0011, 0x0002 }, + { 0x0012, 0x0001 }, + { 0x0010, 0x0005 }, + { 0x0012, 0x0002 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0003 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + + }; + + +const uint16_t c_aauiLCLDHuffEnc27[91][2] = + { + { 0x0006, 0x0006 }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0005, 0x0010 }, + { 0x0005, 0x0011 }, + { 0x0005, 0x0012 }, + { 0x0005, 0x0013 }, + { 0x0005, 0x0014 }, + { 0x0005, 0x0015 }, + { 0x0005, 0x0016 }, + { 0x0005, 0x0017 }, + { 0x0005, 0x0018 }, + { 0x0005, 0x0019 }, + { 0x0005, 0x001a }, + { 0x0005, 0x001b }, + { 0x0005, 0x001c }, + { 0x0005, 0x001d }, + { 0x0005, 0x001e }, + { 0x0005, 0x001f }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0006, 0x0014 }, + { 0x0006, 0x0015 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0007, 0x0008 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0003 }, + { 0x000e, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x000e, 0x0006 }, + { 0x000e, 0x0007 }, + { 0x000f, 0x0003 }, + { 0x000f, 0x0004 }, + { 0x0010, 0x0003 }, + { 0x000f, 0x0005 }, + { 0x0012, 0x0000 }, + { 0x0010, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x0012, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0011, 0x0004 }, + { 0x0011, 0x0005 }, + { 0x0012, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc28[109][2] = + { + { 0x0006, 0x0008 }, + { 0x0005, 0x0010 }, + { 0x0005, 0x0011 }, + { 0x0005, 0x0012 }, + { 0x0005, 0x0013 }, + { 0x0005, 0x0014 }, + { 0x0005, 0x0015 }, + { 0x0005, 0x0016 }, + { 0x0005, 0x0017 }, + { 0x0005, 0x0018 }, + { 0x0005, 0x0019 }, + { 0x0005, 0x001a }, + { 0x0005, 0x001b }, + { 0x0005, 0x001c }, + { 0x0005, 0x001d }, + { 0x0005, 0x001e }, + { 0x0006, 0x0009 }, + { 0x0005, 0x001f }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0006, 0x0014 }, + { 0x0006, 0x0015 }, + { 0x0006, 0x0016 }, + { 0x0006, 0x0017 }, + { 0x0006, 0x0018 }, + { 0x0006, 0x0019 }, + { 0x0006, 0x001a }, + { 0x0006, 0x001b }, + { 0x0006, 0x001c }, + { 0x0006, 0x001d }, + { 0x0006, 0x001e }, + { 0x0006, 0x001f }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0007, 0x0008 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000c, 0x0008 }, + { 0x000c, 0x0009 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x000e, 0x0006 }, + { 0x000e, 0x0007 }, + { 0x0010, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x0010, 0x0005 }, + { 0x000f, 0x0006 }, + { 0x000f, 0x0007 }, + { 0x0010, 0x0006 }, + { 0x0011, 0x0006 }, + { 0x0010, 0x0007 }, + { 0x0013, 0x0000 }, + { 0x0010, 0x0008 }, + { 0x0010, 0x0009 }, + { 0x0013, 0x0001 }, + { 0x0011, 0x0007 }, + { 0x0012, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + + }; + +const uint16_t c_aauiLCLDHuffEnc29[129][2] = + { + { 0x0006, 0x0009 }, + { 0x0005, 0x0019 }, + { 0x0006, 0x000a }, + { 0x0005, 0x001a }, + { 0x0005, 0x001b }, + { 0x0005, 0x001c }, + { 0x0006, 0x000b }, + { 0x0005, 0x001d }, + { 0x0005, 0x001e }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0005, 0x001f }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0006, 0x0014 }, + { 0x0006, 0x0015 }, + { 0x0006, 0x0016 }, + { 0x0006, 0x0017 }, + { 0x0006, 0x0018 }, + { 0x0006, 0x0019 }, + { 0x0006, 0x001a }, + { 0x0006, 0x001b }, + { 0x0006, 0x001c }, + { 0x0006, 0x001d }, + { 0x0006, 0x001e }, + { 0x0006, 0x001f }, + { 0x0006, 0x0020 }, + { 0x0006, 0x0021 }, + { 0x0006, 0x0022 }, + { 0x0006, 0x0023 }, + { 0x0006, 0x0024 }, + { 0x0006, 0x0025 }, + { 0x0006, 0x0026 }, + { 0x0006, 0x0027 }, + { 0x0006, 0x0028 }, + { 0x0006, 0x0029 }, + { 0x0006, 0x002a }, + { 0x0006, 0x002b }, + { 0x0006, 0x002c }, + { 0x0006, 0x002d }, + { 0x0006, 0x002e }, + { 0x0006, 0x002f }, + { 0x0006, 0x0030 }, + { 0x0006, 0x0031 }, + { 0x0007, 0x0007 }, + { 0x0007, 0x0008 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000a, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000c, 0x0008 }, + { 0x000c, 0x0009 }, + { 0x000c, 0x000a }, + { 0x000c, 0x000b }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000d, 0x000a }, + { 0x000d, 0x000b }, + { 0x000e, 0x0006 }, + { 0x000e, 0x0007 }, + { 0x000e, 0x0008 }, + { 0x000e, 0x0009 }, + { 0x000f, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x000f, 0x0006 }, + { 0x000f, 0x0007 }, + { 0x0011, 0x0007 }, + { 0x000f, 0x0008 }, + { 0x0012, 0x0000 }, + { 0x000f, 0x0009 }, + { 0x0010, 0x0005 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + { 0x0012, 0x0001 }, + { 0x0010, 0x0006 }, + { 0x0010, 0x0007 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0012, 0x0008 }, + { 0x0011, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + { 0x0012, 0x000c }, + { 0x0012, 0x000d }, + { 0x0011, 0x0009 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc30[153][2] = + { + { 0x0007, 0x0009 }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0006, 0x0014 }, + { 0x0006, 0x0015 }, + { 0x0006, 0x0016 }, + { 0x0006, 0x0017 }, + { 0x0006, 0x0018 }, + { 0x0006, 0x0019 }, + { 0x0006, 0x001a }, + { 0x0006, 0x001b }, + { 0x0006, 0x001c }, + { 0x0006, 0x001d }, + { 0x0006, 0x001e }, + { 0x0006, 0x001f }, + { 0x0006, 0x0020 }, + { 0x0006, 0x0021 }, + { 0x0006, 0x0022 }, + { 0x0006, 0x0023 }, + { 0x0006, 0x0024 }, + { 0x0006, 0x0025 }, + { 0x0006, 0x0026 }, + { 0x0006, 0x0027 }, + { 0x0006, 0x0028 }, + { 0x0006, 0x0029 }, + { 0x0006, 0x002a }, + { 0x0006, 0x002b }, + { 0x0006, 0x002c }, + { 0x0006, 0x002d }, + { 0x0006, 0x002e }, + { 0x0006, 0x002f }, + { 0x0006, 0x0030 }, + { 0x0006, 0x0031 }, + { 0x0006, 0x0032 }, + { 0x0006, 0x0033 }, + { 0x0006, 0x0034 }, + { 0x0006, 0x0035 }, + { 0x0006, 0x0036 }, + { 0x0006, 0x0037 }, + { 0x0006, 0x0038 }, + { 0x0006, 0x0039 }, + { 0x0006, 0x003a }, + { 0x0006, 0x003b }, + { 0x0006, 0x003c }, + { 0x0006, 0x003d }, + { 0x0006, 0x003e }, + { 0x0006, 0x003f }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0007, 0x0012 }, + { 0x0007, 0x0013 }, + { 0x0007, 0x0014 }, + { 0x0007, 0x0015 }, + { 0x0007, 0x0016 }, + { 0x0007, 0x0017 }, + { 0x0007, 0x0018 }, + { 0x0007, 0x0019 }, + { 0x0007, 0x001a }, + { 0x0007, 0x001b }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0008, 0x000e }, + { 0x0008, 0x000f }, + { 0x0008, 0x0010 }, + { 0x0008, 0x0011 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x0009, 0x000c }, + { 0x0009, 0x000d }, + { 0x0009, 0x000e }, + { 0x000a, 0x0008 }, + { 0x0009, 0x000f }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000b, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000b, 0x000a }, + { 0x000b, 0x000b }, + { 0x000b, 0x000c }, + { 0x000b, 0x000d }, + { 0x000c, 0x0008 }, + { 0x000b, 0x000e }, + { 0x000b, 0x000f }, + { 0x000c, 0x0009 }, + { 0x000c, 0x000a }, + { 0x000d, 0x0008 }, + { 0x000c, 0x000b }, + { 0x000c, 0x000c }, + { 0x000d, 0x0009 }, + { 0x000c, 0x000d }, + { 0x000d, 0x000a }, + { 0x000d, 0x000b }, + { 0x000d, 0x000c }, + { 0x000d, 0x000d }, + { 0x000e, 0x0008 }, + { 0x000d, 0x000e }, + { 0x000d, 0x000f }, + { 0x000e, 0x0009 }, + { 0x000e, 0x000a }, + { 0x000e, 0x000b }, + { 0x000e, 0x000c }, + { 0x000f, 0x0006 }, + { 0x000f, 0x0007 }, + { 0x000f, 0x0008 }, + { 0x0010, 0x0006 }, + { 0x000e, 0x000d }, + { 0x000e, 0x000e }, + { 0x000e, 0x000f }, + { 0x0010, 0x0007 }, + { 0x000f, 0x0009 }, + { 0x0010, 0x0008 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + { 0x000f, 0x000c }, + { 0x000f, 0x000d }, + { 0x0010, 0x0009 }, + { 0x0011, 0x0000 }, + { 0x0011, 0x0001 }, + { 0x0011, 0x0002 }, + { 0x000f, 0x000e }, + { 0x0010, 0x000a }, + { 0x0011, 0x0003 }, + { 0x0011, 0x0004 }, + { 0x0011, 0x0005 }, + { 0x000f, 0x000f }, + { 0x0011, 0x0006 }, + { 0x0011, 0x0007 }, + { 0x0011, 0x0008 }, + { 0x0011, 0x0009 }, + { 0x0011, 0x000a }, + { 0x0011, 0x000b }, + { 0x0010, 0x000b }, + + }; + +const uint16_t c_aauiLCLDHuffEnc31[181][2] = + { + { 0x0007, 0x000b }, + { 0x0006, 0x0015 }, + { 0x0006, 0x0016 }, + { 0x0006, 0x0017 }, + { 0x0006, 0x0018 }, + { 0x0006, 0x0019 }, + { 0x0006, 0x001a }, + { 0x0006, 0x001b }, + { 0x0006, 0x001c }, + { 0x0006, 0x001d }, + { 0x0006, 0x001e }, + { 0x0006, 0x001f }, + { 0x0006, 0x0020 }, + { 0x0006, 0x0021 }, + { 0x0006, 0x0022 }, + { 0x0006, 0x0023 }, + { 0x0006, 0x0024 }, + { 0x0006, 0x0025 }, + { 0x0006, 0x0026 }, + { 0x0006, 0x0027 }, + { 0x0006, 0x0028 }, + { 0x0006, 0x0029 }, + { 0x0006, 0x002a }, + { 0x0006, 0x002b }, + { 0x0006, 0x002c }, + { 0x0006, 0x002d }, + { 0x0006, 0x002e }, + { 0x0006, 0x002f }, + { 0x0006, 0x0030 }, + { 0x0006, 0x0031 }, + { 0x0006, 0x0032 }, + { 0x0006, 0x0033 }, + { 0x0006, 0x0034 }, + { 0x0006, 0x0035 }, + { 0x0006, 0x0036 }, + { 0x0006, 0x0037 }, + { 0x0006, 0x0038 }, + { 0x0006, 0x0039 }, + { 0x0006, 0x003a }, + { 0x0006, 0x003b }, + { 0x0006, 0x003c }, + { 0x0006, 0x003d }, + { 0x0006, 0x003e }, + { 0x0007, 0x000c }, + { 0x0006, 0x003f }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0007, 0x0012 }, + { 0x0007, 0x0013 }, + { 0x0007, 0x0014 }, + { 0x0007, 0x0015 }, + { 0x0007, 0x0016 }, + { 0x0007, 0x0017 }, + { 0x0007, 0x0018 }, + { 0x0007, 0x0019 }, + { 0x0007, 0x001a }, + { 0x0007, 0x001b }, + { 0x0007, 0x001c }, + { 0x0007, 0x001d }, + { 0x0007, 0x001e }, + { 0x0007, 0x001f }, + { 0x0007, 0x0020 }, + { 0x0007, 0x0021 }, + { 0x0007, 0x0022 }, + { 0x0007, 0x0023 }, + { 0x0007, 0x0024 }, + { 0x0007, 0x0025 }, + { 0x0007, 0x0026 }, + { 0x0007, 0x0027 }, + { 0x0007, 0x0028 }, + { 0x0007, 0x0029 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0008, 0x000e }, + { 0x0008, 0x000f }, + { 0x0008, 0x0010 }, + { 0x0008, 0x0011 }, + { 0x0008, 0x0012 }, + { 0x0008, 0x0013 }, + { 0x0008, 0x0014 }, + { 0x0008, 0x0015 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x0009, 0x000c }, + { 0x0009, 0x000d }, + { 0x0009, 0x000e }, + { 0x0009, 0x000f }, + { 0x0009, 0x0010 }, + { 0x0009, 0x0011 }, + { 0x000a, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000a, 0x000e }, + { 0x000a, 0x000f }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000b, 0x000a }, + { 0x000b, 0x000b }, + { 0x000b, 0x000c }, + { 0x000b, 0x000d }, + { 0x000b, 0x000e }, + { 0x000c, 0x0008 }, + { 0x000c, 0x0009 }, + { 0x000b, 0x000f }, + { 0x000c, 0x000a }, + { 0x000c, 0x000b }, + { 0x000c, 0x000c }, + { 0x000c, 0x000d }, + { 0x000d, 0x0008 }, + { 0x000c, 0x000e }, + { 0x000d, 0x0009 }, + { 0x000d, 0x000a }, + { 0x000c, 0x000f }, + { 0x000d, 0x000b }, + { 0x000d, 0x000c }, + { 0x000d, 0x000d }, + { 0x000d, 0x000e }, + { 0x000d, 0x000f }, + { 0x000e, 0x0008 }, + { 0x000e, 0x0009 }, + { 0x000e, 0x000a }, + { 0x000e, 0x000b }, + { 0x000e, 0x000c }, + { 0x000e, 0x000d }, + { 0x000e, 0x000e }, + { 0x000e, 0x000f }, + { 0x000f, 0x0009 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + { 0x000f, 0x000c }, + { 0x0010, 0x0009 }, + { 0x000f, 0x000d }, + { 0x000f, 0x000e }, + { 0x0010, 0x000a }, + { 0x0010, 0x000b }, + { 0x0010, 0x000c }, + { 0x0010, 0x000d }, + { 0x0011, 0x000a }, + { 0x0010, 0x000e }, + { 0x000f, 0x000f }, + { 0x0010, 0x000f }, + { 0x0012, 0x0000 }, + { 0x0012, 0x0001 }, + { 0x0011, 0x000b }, + { 0x0011, 0x000c }, + { 0x0010, 0x0010 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0011, 0x000d }, + { 0x0011, 0x000e }, + { 0x0011, 0x000f }, + { 0x0011, 0x0010 }, + { 0x0011, 0x0011 }, + { 0x0010, 0x0011 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + { 0x0012, 0x000c }, + { 0x0012, 0x000d }, + { 0x0012, 0x000e }, + { 0x0012, 0x000f }, + { 0x0012, 0x0010 }, + { 0x0012, 0x0011 }, + { 0x0012, 0x0012 }, + { 0x0012, 0x0013 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc33[16][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0008, 0x0000 }, + { 0x0008, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + }; + +const uint16_t c_aauiLCLDHuffEnc34[16][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0008, 0x0000 }, + { 0x0008, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + }; + +const uint16_t c_aauiLCLDHuffEnc35[25][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0007, 0x0006 }, + { 0x0009, 0x0000 }, + { 0x0009, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x0007, 0x0007 }, + { 0x0009, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x0009, 0x000c }, + { 0x0009, 0x000d }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + + }; + +const uint16_t c_aauiLCLDHuffEnc36[36][2] = + { + { 0x0001, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0006, 0x0002 }, + { 0x000b, 0x0000 }, + { 0x000b, 0x0001 }, + { 0x000b, 0x0002 }, + { 0x0003, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0008, 0x0005 }, + { 0x000b, 0x0003 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x0006, 0x0003 }, + { 0x0007, 0x0003 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000b, 0x000a }, + { 0x000b, 0x000b }, + { 0x000b, 0x000c }, + { 0x000b, 0x000d }, + { 0x000b, 0x000e }, + { 0x000b, 0x000f }, + { 0x000a, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000a, 0x000e }, + { 0x000a, 0x000f }, + { 0x000a, 0x0010 }, + { 0x000a, 0x0011 }, + { 0x000a, 0x0012 }, + { 0x000a, 0x0013 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc37[36][2] = + { + { 0x0001, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000c, 0x0000 }, + { 0x000c, 0x0001 }, + { 0x000c, 0x0002 }, + { 0x0003, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0006, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x0006, 0x0003 }, + { 0x0007, 0x0001 }, + { 0x000a, 0x0007 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000c, 0x0008 }, + { 0x000c, 0x0009 }, + { 0x000c, 0x000a }, + { 0x000c, 0x000b }, + { 0x000c, 0x000c }, + { 0x000c, 0x000d }, + { 0x000c, 0x000e }, + { 0x000c, 0x000f }, + { 0x000c, 0x0010 }, + { 0x000c, 0x0011 }, + { 0x000c, 0x0012 }, + { 0x000c, 0x0013 }, + { 0x000c, 0x0014 }, + { 0x000c, 0x0015 }, + { 0x000c, 0x0016 }, + { 0x000c, 0x0017 }, + { 0x000c, 0x0018 }, + { 0x000c, 0x0019 }, + { 0x000b, 0x000d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc38[49][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000c, 0x0012 }, + { 0x000d, 0x0000 }, + { 0x000d, 0x0001 }, + { 0x000d, 0x0002 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000b, 0x000a }, + { 0x000d, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0009, 0x0003 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000c, 0x0013 }, + { 0x000b, 0x000b }, + { 0x000d, 0x000a }, + { 0x000d, 0x000b }, + { 0x000d, 0x000c }, + { 0x000d, 0x000d }, + { 0x000d, 0x000e }, + { 0x000d, 0x000f }, + { 0x000d, 0x0010 }, + { 0x000d, 0x0011 }, + { 0x000d, 0x0012 }, + { 0x000d, 0x0013 }, + { 0x000d, 0x0014 }, + { 0x000d, 0x0015 }, + { 0x000d, 0x0016 }, + { 0x000d, 0x0017 }, + { 0x000d, 0x0018 }, + { 0x000d, 0x0019 }, + { 0x000d, 0x001a }, + { 0x000d, 0x001b }, + { 0x000d, 0x001c }, + { 0x000d, 0x001d }, + { 0x000d, 0x001e }, + { 0x000d, 0x001f }, + { 0x000d, 0x0020 }, + { 0x000d, 0x0021 }, + { 0x000d, 0x0022 }, + { 0x000d, 0x0023 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc39[64][2] = + { + { 0x0001, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000a, 0x0002 }, + { 0x000f, 0x0000 }, + { 0x000f, 0x0001 }, + { 0x000f, 0x0002 }, + { 0x000f, 0x0003 }, + { 0x0003, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000a, 0x0003 }, + { 0x000f, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x000f, 0x0006 }, + { 0x000f, 0x0007 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0009, 0x0003 }, + { 0x000d, 0x000e }, + { 0x000f, 0x0008 }, + { 0x000f, 0x0009 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000d, 0x000f }, + { 0x000f, 0x000c }, + { 0x000f, 0x000d }, + { 0x000f, 0x000e }, + { 0x000f, 0x000f }, + { 0x000f, 0x0010 }, + { 0x000f, 0x0011 }, + { 0x000f, 0x0012 }, + { 0x000f, 0x0013 }, + { 0x000f, 0x0014 }, + { 0x000f, 0x0015 }, + { 0x000f, 0x0016 }, + { 0x000f, 0x0017 }, + { 0x000f, 0x0018 }, + { 0x000f, 0x0019 }, + { 0x000f, 0x001a }, + { 0x000f, 0x001b }, + { 0x000f, 0x001c }, + { 0x000f, 0x001d }, + { 0x000f, 0x001e }, + { 0x000f, 0x001f }, + { 0x000f, 0x0020 }, + { 0x000f, 0x0021 }, + { 0x000f, 0x0022 }, + { 0x000f, 0x0023 }, + { 0x000f, 0x0024 }, + { 0x000f, 0x0025 }, + { 0x000f, 0x0026 }, + { 0x000f, 0x0027 }, + { 0x000f, 0x0028 }, + { 0x000f, 0x0029 }, + { 0x000e, 0x0015 }, + { 0x000e, 0x0016 }, + { 0x000e, 0x0017 }, + { 0x000e, 0x0018 }, + { 0x000e, 0x0019 }, + { 0x000e, 0x001a }, + { 0x000e, 0x001b }, + }; + +const uint16_t c_aauiLCLDHuffEnc40[81][2] = + { + { 0x0001, 0x0001 }, + { 0x0002, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000b, 0x0002 }, + { 0x000f, 0x0011 }, + { 0x0011, 0x0000 }, + { 0x0011, 0x0001 }, + { 0x0011, 0x0002 }, + { 0x0011, 0x0003 }, + { 0x0003, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000a, 0x0002 }, + { 0x000e, 0x0009 }, + { 0x0011, 0x0004 }, + { 0x0011, 0x0005 }, + { 0x0011, 0x0006 }, + { 0x0011, 0x0007 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x000d, 0x0005 }, + { 0x0011, 0x0008 }, + { 0x0011, 0x0009 }, + { 0x0011, 0x000a }, + { 0x0011, 0x000b }, + { 0x0011, 0x000c }, + { 0x000b, 0x0003 }, + { 0x000a, 0x0003 }, + { 0x000c, 0x0003 }, + { 0x0011, 0x000d }, + { 0x0011, 0x000e }, + { 0x0011, 0x000f }, + { 0x0011, 0x0010 }, + { 0x0011, 0x0011 }, + { 0x0011, 0x0012 }, + { 0x0011, 0x0013 }, + { 0x0011, 0x0014 }, + { 0x0011, 0x0015 }, + { 0x0011, 0x0016 }, + { 0x0011, 0x0017 }, + { 0x0011, 0x0018 }, + { 0x0011, 0x0019 }, + { 0x0011, 0x001a }, + { 0x0011, 0x001b }, + { 0x0011, 0x001c }, + { 0x0011, 0x001d }, + { 0x0011, 0x001e }, + { 0x0011, 0x001f }, + { 0x0011, 0x0020 }, + { 0x0011, 0x0021 }, + { 0x0011, 0x0022 }, + { 0x0011, 0x0023 }, + { 0x0011, 0x0024 }, + { 0x0011, 0x0025 }, + { 0x0011, 0x0026 }, + { 0x0011, 0x0027 }, + { 0x0011, 0x0028 }, + { 0x0011, 0x0029 }, + { 0x0011, 0x002a }, + { 0x0011, 0x002b }, + { 0x0011, 0x002c }, + { 0x0011, 0x002d }, + { 0x0011, 0x002e }, + { 0x0011, 0x002f }, + { 0x0011, 0x0030 }, + { 0x0011, 0x0031 }, + { 0x0011, 0x0032 }, + { 0x0011, 0x0033 }, + { 0x0011, 0x0034 }, + { 0x0011, 0x0035 }, + { 0x0011, 0x0036 }, + { 0x0011, 0x0037 }, + { 0x0011, 0x0038 }, + { 0x0011, 0x0039 }, + { 0x0011, 0x003a }, + { 0x0011, 0x003b }, + { 0x0010, 0x001e }, + { 0x0010, 0x001f }, + { 0x0010, 0x0020 }, + { 0x0010, 0x0021 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc41[100][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x0011, 0x0014 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0002, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x0010, 0x000b }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x000d, 0x0002 }, + { 0x0011, 0x0015 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000d, 0x0003 }, + { 0x0010, 0x000c }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0010, 0x000d }, + { 0x000f, 0x0007 }, + { 0x0012, 0x0027 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc42[169][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000e, 0x0006 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0009, 0x0002 }, + { 0x000d, 0x0004 }, + { 0x0010, 0x0013 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0008, 0x0002 }, + { 0x000b, 0x0002 }, + { 0x000f, 0x000b }, + { 0x0011, 0x0025 }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0009, 0x0003 }, + { 0x0008, 0x0003 }, + { 0x000b, 0x0003 }, + { 0x000d, 0x0005 }, + { 0x0010, 0x0014 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0007 }, + { 0x0010, 0x0015 }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0012, 0x0045 }, + { 0x0013, 0x0027 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x0013, 0x0054 }, + { 0x0013, 0x0055 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0013, 0x0062 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x0013, 0x0066 }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0012, 0x0046 }, + { 0x0012, 0x0047 }, + { 0x0012, 0x0048 }, + { 0x0012, 0x0049 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc43[196][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0009, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x0010, 0x0017 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0009, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x0010, 0x0018 }, + { 0x0012, 0x0050 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0008, 0x0003 }, + { 0x000a, 0x0002 }, + { 0x000d, 0x0004 }, + { 0x0011, 0x002a }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000a, 0x0003 }, + { 0x000c, 0x0005 }, + { 0x000f, 0x000d }, + { 0x0012, 0x0051 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0005 }, + { 0x000f, 0x000e }, + { 0x0011, 0x002b }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0011, 0x002c }, + { 0x000f, 0x000f }, + { 0x0010, 0x0019 }, + { 0x0012, 0x0052 }, + { 0x0012, 0x0053 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0011, 0x002d }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x0013, 0x0054 }, + { 0x0013, 0x0055 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0013, 0x0062 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x0013, 0x0066 }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x0013, 0x008b }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0013, 0x008e }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0013, 0x0091 }, + { 0x0013, 0x0092 }, + { 0x0013, 0x0093 }, + { 0x0013, 0x0094 }, + { 0x0013, 0x0095 }, + { 0x0013, 0x0096 }, + { 0x0013, 0x0097 }, + { 0x0013, 0x0098 }, + { 0x0013, 0x0099 }, + { 0x0013, 0x009a }, + { 0x0013, 0x009b }, + { 0x0013, 0x009c }, + { 0x0013, 0x009d }, + { 0x0013, 0x009e }, + { 0x0013, 0x009f }, + + }; + +const uint16_t c_aauiLCLDHuffEnc44[289][2] = + { + { 0x0001, 0x0001 }, + { 0x0003, 0x0001 }, + { 0x0006, 0x0002 }, + { 0x0008, 0x0002 }, + { 0x000b, 0x0002 }, + { 0x000f, 0x000a }, + { 0x0011, 0x0022 }, + { 0x0014, 0x0000 }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0014, 0x0006 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0014, 0x0009 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x000b, 0x0003 }, + { 0x000e, 0x0007 }, + { 0x0012, 0x003f }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0014, 0x000c }, + { 0x0014, 0x000d }, + { 0x0014, 0x000e }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0014, 0x0013 }, + { 0x0006, 0x0003 }, + { 0x0005, 0x0003 }, + { 0x0007, 0x0003 }, + { 0x0009, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000f, 0x000b }, + { 0x0012, 0x0040 }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + { 0x0014, 0x001a }, + { 0x0014, 0x001b }, + { 0x0014, 0x001c }, + { 0x0014, 0x001d }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0009, 0x0003 }, + { 0x000b, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x0010, 0x0013 }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0014, 0x0020 }, + { 0x0014, 0x0021 }, + { 0x0014, 0x0022 }, + { 0x0014, 0x0023 }, + { 0x0014, 0x0024 }, + { 0x0014, 0x0025 }, + { 0x0014, 0x0026 }, + { 0x0014, 0x0027 }, + { 0x0014, 0x0028 }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000e, 0x0008 }, + { 0x0011, 0x0023 }, + { 0x0012, 0x0041 }, + { 0x0014, 0x0029 }, + { 0x0014, 0x002a }, + { 0x0013, 0x007b }, + { 0x0014, 0x002b }, + { 0x0014, 0x002c }, + { 0x0014, 0x002d }, + { 0x0014, 0x002e }, + { 0x0014, 0x002f }, + { 0x0014, 0x0030 }, + { 0x0014, 0x0031 }, + { 0x0014, 0x0032 }, + { 0x000f, 0x000c }, + { 0x000e, 0x0009 }, + { 0x000f, 0x000d }, + { 0x0011, 0x0024 }, + { 0x0012, 0x0042 }, + { 0x0014, 0x0033 }, + { 0x0014, 0x0034 }, + { 0x0014, 0x0035 }, + { 0x0014, 0x0036 }, + { 0x0014, 0x0037 }, + { 0x0014, 0x0038 }, + { 0x0014, 0x0039 }, + { 0x0014, 0x003a }, + { 0x0014, 0x003b }, + { 0x0014, 0x003c }, + { 0x0014, 0x003d }, + { 0x0014, 0x003e }, + { 0x0013, 0x007c }, + { 0x0011, 0x0025 }, + { 0x0012, 0x0043 }, + { 0x0014, 0x003f }, + { 0x0014, 0x0040 }, + { 0x0014, 0x0041 }, + { 0x0014, 0x0042 }, + { 0x0014, 0x0043 }, + { 0x0014, 0x0044 }, + { 0x0014, 0x0045 }, + { 0x0014, 0x0046 }, + { 0x0014, 0x0047 }, + { 0x0014, 0x0048 }, + { 0x0014, 0x0049 }, + { 0x0014, 0x004a }, + { 0x0014, 0x004b }, + { 0x0014, 0x004c }, + { 0x0014, 0x004d }, + { 0x0014, 0x004e }, + { 0x0014, 0x004f }, + { 0x0014, 0x0050 }, + { 0x0014, 0x0051 }, + { 0x0014, 0x0052 }, + { 0x0014, 0x0053 }, + { 0x0014, 0x0054 }, + { 0x0014, 0x0055 }, + { 0x0014, 0x0056 }, + { 0x0014, 0x0057 }, + { 0x0014, 0x0058 }, + { 0x0014, 0x0059 }, + { 0x0014, 0x005a }, + { 0x0014, 0x005b }, + { 0x0014, 0x005c }, + { 0x0014, 0x005d }, + { 0x0014, 0x005e }, + { 0x0014, 0x005f }, + { 0x0014, 0x0060 }, + { 0x0014, 0x0061 }, + { 0x0014, 0x0062 }, + { 0x0014, 0x0063 }, + { 0x0014, 0x0064 }, + { 0x0014, 0x0065 }, + { 0x0014, 0x0066 }, + { 0x0014, 0x0067 }, + { 0x0014, 0x0068 }, + { 0x0014, 0x0069 }, + { 0x0014, 0x006a }, + { 0x0014, 0x006b }, + { 0x0014, 0x006c }, + { 0x0014, 0x006d }, + { 0x0014, 0x006e }, + { 0x0014, 0x006f }, + { 0x0014, 0x0070 }, + { 0x0014, 0x0071 }, + { 0x0014, 0x0072 }, + { 0x0014, 0x0073 }, + { 0x0014, 0x0074 }, + { 0x0014, 0x0075 }, + { 0x0014, 0x0076 }, + { 0x0014, 0x0077 }, + { 0x0014, 0x0078 }, + { 0x0014, 0x0079 }, + { 0x0014, 0x007a }, + { 0x0014, 0x007b }, + { 0x0014, 0x007c }, + { 0x0014, 0x007d }, + { 0x0014, 0x007e }, + { 0x0014, 0x007f }, + { 0x0014, 0x0080 }, + { 0x0014, 0x0081 }, + { 0x0014, 0x0082 }, + { 0x0014, 0x0083 }, + { 0x0014, 0x0084 }, + { 0x0014, 0x0085 }, + { 0x0014, 0x0086 }, + { 0x0014, 0x0087 }, + { 0x0014, 0x0088 }, + { 0x0014, 0x0089 }, + { 0x0014, 0x008a }, + { 0x0014, 0x008b }, + { 0x0014, 0x008c }, + { 0x0014, 0x008d }, + { 0x0014, 0x008e }, + { 0x0014, 0x008f }, + { 0x0014, 0x0090 }, + { 0x0014, 0x0091 }, + { 0x0014, 0x0092 }, + { 0x0014, 0x0093 }, + { 0x0014, 0x0094 }, + { 0x0014, 0x0095 }, + { 0x0014, 0x0096 }, + { 0x0014, 0x0097 }, + { 0x0014, 0x0098 }, + { 0x0014, 0x0099 }, + { 0x0014, 0x009a }, + { 0x0014, 0x009b }, + { 0x0014, 0x009c }, + { 0x0014, 0x009d }, + { 0x0014, 0x009e }, + { 0x0014, 0x009f }, + { 0x0014, 0x00a0 }, + { 0x0014, 0x00a1 }, + { 0x0014, 0x00a2 }, + { 0x0014, 0x00a3 }, + { 0x0014, 0x00a4 }, + { 0x0014, 0x00a5 }, + { 0x0014, 0x00a6 }, + { 0x0014, 0x00a7 }, + { 0x0014, 0x00a8 }, + { 0x0014, 0x00a9 }, + { 0x0014, 0x00aa }, + { 0x0014, 0x00ab }, + { 0x0014, 0x00ac }, + { 0x0014, 0x00ad }, + { 0x0014, 0x00ae }, + { 0x0014, 0x00af }, + { 0x0014, 0x00b0 }, + { 0x0014, 0x00b1 }, + { 0x0014, 0x00b2 }, + { 0x0014, 0x00b3 }, + { 0x0014, 0x00b4 }, + { 0x0014, 0x00b5 }, + { 0x0014, 0x00b6 }, + { 0x0014, 0x00b7 }, + { 0x0014, 0x00b8 }, + { 0x0014, 0x00b9 }, + { 0x0014, 0x00ba }, + { 0x0014, 0x00bb }, + { 0x0014, 0x00bc }, + { 0x0014, 0x00bd }, + { 0x0014, 0x00be }, + { 0x0014, 0x00bf }, + { 0x0014, 0x00c0 }, + { 0x0014, 0x00c1 }, + { 0x0014, 0x00c2 }, + { 0x0014, 0x00c3 }, + { 0x0014, 0x00c4 }, + { 0x0014, 0x00c5 }, + { 0x0014, 0x00c6 }, + { 0x0014, 0x00c7 }, + { 0x0014, 0x00c8 }, + { 0x0014, 0x00c9 }, + { 0x0014, 0x00ca }, + { 0x0014, 0x00cb }, + { 0x0014, 0x00cc }, + { 0x0014, 0x00cd }, + { 0x0014, 0x00ce }, + { 0x0014, 0x00cf }, + { 0x0014, 0x00d0 }, + { 0x0014, 0x00d1 }, + { 0x0014, 0x00d2 }, + { 0x0014, 0x00d3 }, + { 0x0014, 0x00d4 }, + { 0x0014, 0x00d5 }, + { 0x0014, 0x00d6 }, + { 0x0014, 0x00d7 }, + { 0x0014, 0x00d8 }, + { 0x0014, 0x00d9 }, + { 0x0014, 0x00da }, + { 0x0014, 0x00db }, + { 0x0014, 0x00dc }, + { 0x0014, 0x00dd }, + { 0x0014, 0x00de }, + { 0x0014, 0x00df }, + { 0x0014, 0x00e0 }, + { 0x0014, 0x00e1 }, + { 0x0014, 0x00e2 }, + { 0x0014, 0x00e3 }, + { 0x0014, 0x00e4 }, + { 0x0014, 0x00e5 }, + { 0x0014, 0x00e6 }, + { 0x0014, 0x00e7 }, + { 0x0014, 0x00e8 }, + { 0x0014, 0x00e9 }, + { 0x0014, 0x00ea }, + { 0x0014, 0x00eb }, + { 0x0014, 0x00ec }, + { 0x0014, 0x00ed }, + { 0x0014, 0x00ee }, + { 0x0014, 0x00ef }, + { 0x0014, 0x00f0 }, + { 0x0014, 0x00f1 }, + { 0x0014, 0x00f2 }, + { 0x0014, 0x00f3 }, + { 0x0014, 0x00f4 }, + { 0x0014, 0x00f5 }, + { 0x0013, 0x007d }, + + }; + + +const uint16_t c_aauiLCLDHuffEnc45[324][2] = + { + { 0x0002, 0x0002 }, + { 0x0003, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0007, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000c, 0x0005 }, + { 0x0010, 0x0025 }, + { 0x0012, 0x0088 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0006, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x000b, 0x0004 }, + { 0x000f, 0x0014 }, + { 0x0011, 0x0048 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0005, 0x0005 }, + { 0x0004, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0007, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000d, 0x0007 }, + { 0x000f, 0x0015 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0007, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0005 }, + { 0x0009, 0x0005 }, + { 0x000b, 0x0005 }, + { 0x000d, 0x0008 }, + { 0x0010, 0x0026 }, + { 0x0012, 0x0089 }, + { 0x0012, 0x008a }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x000a, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000d, 0x0009 }, + { 0x000f, 0x0016 }, + { 0x0011, 0x0049 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x000c, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0007 }, + { 0x000e, 0x000d }, + { 0x0010, 0x0027 }, + { 0x0012, 0x008b }, + { 0x0012, 0x008c }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x000f, 0x0017 }, + { 0x000f, 0x0018 }, + { 0x000f, 0x0019 }, + { 0x0012, 0x008d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0012, 0x008e }, + { 0x0012, 0x008f }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x0013, 0x0054 }, + { 0x0013, 0x0055 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0013, 0x0062 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x0013, 0x0066 }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x0013, 0x008b }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0013, 0x008e }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0013, 0x0091 }, + { 0x0013, 0x0092 }, + { 0x0013, 0x0093 }, + { 0x0013, 0x0094 }, + { 0x0013, 0x0095 }, + { 0x0013, 0x0096 }, + { 0x0013, 0x0097 }, + { 0x0013, 0x0098 }, + { 0x0013, 0x0099 }, + { 0x0013, 0x009a }, + { 0x0013, 0x009b }, + { 0x0013, 0x009c }, + { 0x0013, 0x009d }, + { 0x0013, 0x009e }, + { 0x0013, 0x009f }, + { 0x0013, 0x00a0 }, + { 0x0013, 0x00a1 }, + { 0x0013, 0x00a2 }, + { 0x0013, 0x00a3 }, + { 0x0013, 0x00a4 }, + { 0x0013, 0x00a5 }, + { 0x0013, 0x00a6 }, + { 0x0013, 0x00a7 }, + { 0x0013, 0x00a8 }, + { 0x0013, 0x00a9 }, + { 0x0013, 0x00aa }, + { 0x0013, 0x00ab }, + { 0x0013, 0x00ac }, + { 0x0013, 0x00ad }, + { 0x0013, 0x00ae }, + { 0x0013, 0x00af }, + { 0x0013, 0x00b0 }, + { 0x0013, 0x00b1 }, + { 0x0013, 0x00b2 }, + { 0x0013, 0x00b3 }, + { 0x0013, 0x00b4 }, + { 0x0013, 0x00b5 }, + { 0x0013, 0x00b6 }, + { 0x0013, 0x00b7 }, + { 0x0013, 0x00b8 }, + { 0x0013, 0x00b9 }, + { 0x0013, 0x00ba }, + { 0x0013, 0x00bb }, + { 0x0013, 0x00bc }, + { 0x0013, 0x00bd }, + { 0x0013, 0x00be }, + { 0x0013, 0x00bf }, + { 0x0013, 0x00c0 }, + { 0x0013, 0x00c1 }, + { 0x0013, 0x00c2 }, + { 0x0013, 0x00c3 }, + { 0x0013, 0x00c4 }, + { 0x0013, 0x00c5 }, + { 0x0013, 0x00c6 }, + { 0x0013, 0x00c7 }, + { 0x0013, 0x00c8 }, + { 0x0013, 0x00c9 }, + { 0x0013, 0x00ca }, + { 0x0013, 0x00cb }, + { 0x0013, 0x00cc }, + { 0x0013, 0x00cd }, + { 0x0013, 0x00ce }, + { 0x0013, 0x00cf }, + { 0x0013, 0x00d0 }, + { 0x0013, 0x00d1 }, + { 0x0013, 0x00d2 }, + { 0x0013, 0x00d3 }, + { 0x0013, 0x00d4 }, + { 0x0013, 0x00d5 }, + { 0x0013, 0x00d6 }, + { 0x0013, 0x00d7 }, + { 0x0013, 0x00d8 }, + { 0x0013, 0x00d9 }, + { 0x0013, 0x00da }, + { 0x0013, 0x00db }, + { 0x0013, 0x00dc }, + { 0x0013, 0x00dd }, + { 0x0013, 0x00de }, + { 0x0013, 0x00df }, + { 0x0013, 0x00e0 }, + { 0x0013, 0x00e1 }, + { 0x0013, 0x00e2 }, + { 0x0013, 0x00e3 }, + { 0x0013, 0x00e4 }, + { 0x0013, 0x00e5 }, + { 0x0013, 0x00e6 }, + { 0x0013, 0x00e7 }, + { 0x0013, 0x00e8 }, + { 0x0013, 0x00e9 }, + { 0x0013, 0x00ea }, + { 0x0013, 0x00eb }, + { 0x0013, 0x00ec }, + { 0x0013, 0x00ed }, + { 0x0013, 0x00ee }, + { 0x0013, 0x00ef }, + { 0x0013, 0x00f0 }, + { 0x0013, 0x00f1 }, + { 0x0013, 0x00f2 }, + { 0x0013, 0x00f3 }, + { 0x0013, 0x00f4 }, + { 0x0013, 0x00f5 }, + { 0x0013, 0x00f6 }, + { 0x0013, 0x00f7 }, + { 0x0013, 0x00f8 }, + { 0x0013, 0x00f9 }, + { 0x0013, 0x00fa }, + { 0x0013, 0x00fb }, + { 0x0013, 0x00fc }, + { 0x0013, 0x00fd }, + { 0x0013, 0x00fe }, + { 0x0013, 0x00ff }, + { 0x0013, 0x0100 }, + { 0x0013, 0x0101 }, + { 0x0013, 0x0102 }, + { 0x0013, 0x0103 }, + { 0x0013, 0x0104 }, + { 0x0013, 0x0105 }, + { 0x0013, 0x0106 }, + { 0x0013, 0x0107 }, + { 0x0013, 0x0108 }, + { 0x0013, 0x0109 }, + { 0x0013, 0x010a }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0013, 0x010f }, + + }; + +const uint16_t c_aauiLCLDHuffEnc46[400][2] = + { + { 0x0002, 0x0002 }, + { 0x0003, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000d, 0x000a }, + { 0x000f, 0x0018 }, + { 0x0012, 0x00a6 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0006, 0x0004 }, + { 0x0008, 0x0004 }, + { 0x000a, 0x0006 }, + { 0x000c, 0x0008 }, + { 0x000e, 0x0011 }, + { 0x0012, 0x00a7 }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0007, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000d, 0x000b }, + { 0x000f, 0x0019 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0007, 0x0006 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0005 }, + { 0x000a, 0x0007 }, + { 0x000c, 0x0009 }, + { 0x000e, 0x0012 }, + { 0x000f, 0x001a }, + { 0x0012, 0x00a8 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0009, 0x0007 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x000a, 0x0008 }, + { 0x000b, 0x0008 }, + { 0x000d, 0x000c }, + { 0x000e, 0x0013 }, + { 0x0010, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x000b, 0x0009 }, + { 0x000a, 0x0009 }, + { 0x000b, 0x000a }, + { 0x000b, 0x000b }, + { 0x000d, 0x000d }, + { 0x000f, 0x001b }, + { 0x0010, 0x002d }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x000d, 0x000e }, + { 0x000c, 0x000a }, + { 0x000c, 0x000b }, + { 0x000d, 0x000f }, + { 0x000f, 0x001c }, + { 0x000f, 0x001d }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x000f, 0x001e }, + { 0x000f, 0x001f }, + { 0x000f, 0x0020 }, + { 0x000f, 0x0021 }, + { 0x0010, 0x002e }, + { 0x0012, 0x00a9 }, + { 0x0013, 0x0054 }, + { 0x0013, 0x0055 }, + { 0x0012, 0x00aa }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0010, 0x002f }, + { 0x0013, 0x0062 }, + { 0x0011, 0x0057 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x0013, 0x0066 }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x0013, 0x008b }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0013, 0x008e }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0013, 0x0091 }, + { 0x0013, 0x0092 }, + { 0x0013, 0x0093 }, + { 0x0013, 0x0094 }, + { 0x0013, 0x0095 }, + { 0x0013, 0x0096 }, + { 0x0013, 0x0097 }, + { 0x0013, 0x0098 }, + { 0x0013, 0x0099 }, + { 0x0013, 0x009a }, + { 0x0013, 0x009b }, + { 0x0013, 0x009c }, + { 0x0013, 0x009d }, + { 0x0013, 0x009e }, + { 0x0013, 0x009f }, + { 0x0013, 0x00a0 }, + { 0x0013, 0x00a1 }, + { 0x0013, 0x00a2 }, + { 0x0013, 0x00a3 }, + { 0x0013, 0x00a4 }, + { 0x0013, 0x00a5 }, + { 0x0013, 0x00a6 }, + { 0x0013, 0x00a7 }, + { 0x0013, 0x00a8 }, + { 0x0013, 0x00a9 }, + { 0x0013, 0x00aa }, + { 0x0013, 0x00ab }, + { 0x0013, 0x00ac }, + { 0x0013, 0x00ad }, + { 0x0013, 0x00ae }, + { 0x0013, 0x00af }, + { 0x0013, 0x00b0 }, + { 0x0013, 0x00b1 }, + { 0x0013, 0x00b2 }, + { 0x0013, 0x00b3 }, + { 0x0013, 0x00b4 }, + { 0x0013, 0x00b5 }, + { 0x0013, 0x00b6 }, + { 0x0013, 0x00b7 }, + { 0x0013, 0x00b8 }, + { 0x0013, 0x00b9 }, + { 0x0013, 0x00ba }, + { 0x0013, 0x00bb }, + { 0x0013, 0x00bc }, + { 0x0013, 0x00bd }, + { 0x0013, 0x00be }, + { 0x0013, 0x00bf }, + { 0x0013, 0x00c0 }, + { 0x0013, 0x00c1 }, + { 0x0013, 0x00c2 }, + { 0x0013, 0x00c3 }, + { 0x0013, 0x00c4 }, + { 0x0013, 0x00c5 }, + { 0x0013, 0x00c6 }, + { 0x0013, 0x00c7 }, + { 0x0013, 0x00c8 }, + { 0x0013, 0x00c9 }, + { 0x0013, 0x00ca }, + { 0x0013, 0x00cb }, + { 0x0013, 0x00cc }, + { 0x0013, 0x00cd }, + { 0x0013, 0x00ce }, + { 0x0013, 0x00cf }, + { 0x0013, 0x00d0 }, + { 0x0013, 0x00d1 }, + { 0x0013, 0x00d2 }, + { 0x0013, 0x00d3 }, + { 0x0013, 0x00d4 }, + { 0x0013, 0x00d5 }, + { 0x0013, 0x00d6 }, + { 0x0013, 0x00d7 }, + { 0x0013, 0x00d8 }, + { 0x0013, 0x00d9 }, + { 0x0013, 0x00da }, + { 0x0013, 0x00db }, + { 0x0013, 0x00dc }, + { 0x0013, 0x00dd }, + { 0x0013, 0x00de }, + { 0x0013, 0x00df }, + { 0x0013, 0x00e0 }, + { 0x0013, 0x00e1 }, + { 0x0013, 0x00e2 }, + { 0x0013, 0x00e3 }, + { 0x0013, 0x00e4 }, + { 0x0013, 0x00e5 }, + { 0x0013, 0x00e6 }, + { 0x0013, 0x00e7 }, + { 0x0013, 0x00e8 }, + { 0x0013, 0x00e9 }, + { 0x0013, 0x00ea }, + { 0x0013, 0x00eb }, + { 0x0013, 0x00ec }, + { 0x0013, 0x00ed }, + { 0x0013, 0x00ee }, + { 0x0013, 0x00ef }, + { 0x0013, 0x00f0 }, + { 0x0013, 0x00f1 }, + { 0x0013, 0x00f2 }, + { 0x0013, 0x00f3 }, + { 0x0013, 0x00f4 }, + { 0x0013, 0x00f5 }, + { 0x0013, 0x00f6 }, + { 0x0013, 0x00f7 }, + { 0x0013, 0x00f8 }, + { 0x0013, 0x00f9 }, + { 0x0013, 0x00fa }, + { 0x0013, 0x00fb }, + { 0x0013, 0x00fc }, + { 0x0013, 0x00fd }, + { 0x0013, 0x00fe }, + { 0x0013, 0x00ff }, + { 0x0013, 0x0100 }, + { 0x0013, 0x0101 }, + { 0x0013, 0x0102 }, + { 0x0013, 0x0103 }, + { 0x0013, 0x0104 }, + { 0x0013, 0x0105 }, + { 0x0013, 0x0106 }, + { 0x0013, 0x0107 }, + { 0x0013, 0x0108 }, + { 0x0013, 0x0109 }, + { 0x0013, 0x010a }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0013, 0x010f }, + { 0x0013, 0x0110 }, + { 0x0013, 0x0111 }, + { 0x0013, 0x0112 }, + { 0x0013, 0x0113 }, + { 0x0013, 0x0114 }, + { 0x0013, 0x0115 }, + { 0x0013, 0x0116 }, + { 0x0013, 0x0117 }, + { 0x0013, 0x0118 }, + { 0x0013, 0x0119 }, + { 0x0013, 0x011a }, + { 0x0013, 0x011b }, + { 0x0013, 0x011c }, + { 0x0013, 0x011d }, + { 0x0013, 0x011e }, + { 0x0013, 0x011f }, + { 0x0013, 0x0120 }, + { 0x0013, 0x0121 }, + { 0x0013, 0x0122 }, + { 0x0013, 0x0123 }, + { 0x0013, 0x0124 }, + { 0x0013, 0x0125 }, + { 0x0013, 0x0126 }, + { 0x0013, 0x0127 }, + { 0x0013, 0x0128 }, + { 0x0013, 0x0129 }, + { 0x0013, 0x012a }, + { 0x0013, 0x012b }, + { 0x0013, 0x012c }, + { 0x0013, 0x012d }, + { 0x0013, 0x012e }, + { 0x0013, 0x012f }, + { 0x0013, 0x0130 }, + { 0x0013, 0x0131 }, + { 0x0013, 0x0132 }, + { 0x0013, 0x0133 }, + { 0x0013, 0x0134 }, + { 0x0013, 0x0135 }, + { 0x0013, 0x0136 }, + { 0x0013, 0x0137 }, + { 0x0013, 0x0138 }, + { 0x0013, 0x0139 }, + { 0x0013, 0x013a }, + { 0x0013, 0x013b }, + { 0x0013, 0x013c }, + { 0x0013, 0x013d }, + { 0x0013, 0x013e }, + { 0x0013, 0x013f }, + { 0x0013, 0x0140 }, + { 0x0013, 0x0141 }, + { 0x0013, 0x0142 }, + { 0x0013, 0x0143 }, + { 0x0013, 0x0144 }, + { 0x0013, 0x0145 }, + { 0x0013, 0x0146 }, + { 0x0013, 0x0147 }, + { 0x0013, 0x0148 }, + { 0x0013, 0x0149 }, + { 0x0013, 0x014a }, + { 0x0013, 0x014b }, + { 0x0012, 0x00ab }, + { 0x0012, 0x00ac }, + { 0x0012, 0x00ad }, + }; + +const uint16_t c_aauiLCLDHuffEnc47[576][2] = + { + { 0x0002, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0005 }, + { 0x0006, 0x0004 }, + { 0x0008, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000c, 0x000b }, + { 0x000d, 0x000d }, + { 0x0010, 0x0041 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0004, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000d, 0x000e }, + { 0x000f, 0x0025 }, + { 0x000f, 0x0026 }, + { 0x0012, 0x00f6 }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0005, 0x0006 }, + { 0x0004, 0x0005 }, + { 0x0005, 0x0007 }, + { 0x0006, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0009, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000d, 0x000f }, + { 0x000f, 0x0027 }, + { 0x0012, 0x00f7 }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0007, 0x0006 }, + { 0x0009, 0x0008 }, + { 0x000a, 0x0008 }, + { 0x000c, 0x000c }, + { 0x000e, 0x0017 }, + { 0x0010, 0x0042 }, + { 0x0012, 0x00f8 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0008, 0x0008 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0009 }, + { 0x0009, 0x0009 }, + { 0x000a, 0x0009 }, + { 0x000b, 0x0009 }, + { 0x000d, 0x0010 }, + { 0x000f, 0x0028 }, + { 0x000f, 0x0029 }, + { 0x0011, 0x007f }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x000a, 0x000a }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x000a, 0x000b }, + { 0x000b, 0x000a }, + { 0x000d, 0x0011 }, + { 0x000f, 0x002a }, + { 0x0010, 0x0043 }, + { 0x0012, 0x00f9 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x0013, 0x0054 }, + { 0x000b, 0x000b }, + { 0x000b, 0x000c }, + { 0x000b, 0x000d }, + { 0x000c, 0x000d }, + { 0x000d, 0x0012 }, + { 0x000e, 0x0018 }, + { 0x0010, 0x0044 }, + { 0x0013, 0x0055 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0013, 0x0062 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x000e, 0x0019 }, + { 0x000d, 0x0013 }, + { 0x000d, 0x0014 }, + { 0x000d, 0x0015 }, + { 0x000f, 0x002b }, + { 0x0010, 0x0045 }, + { 0x0013, 0x0066 }, + { 0x0012, 0x00fa }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0010, 0x0046 }, + { 0x000f, 0x002c }, + { 0x000f, 0x002d }, + { 0x0010, 0x0047 }, + { 0x0011, 0x0080 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x0010, 0x0048 }, + { 0x0010, 0x0049 }, + { 0x0011, 0x0081 }, + { 0x0013, 0x008b }, + { 0x0012, 0x00fb }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0013, 0x008e }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0013, 0x0091 }, + { 0x0013, 0x0092 }, + { 0x0013, 0x0093 }, + { 0x0013, 0x0094 }, + { 0x0013, 0x0095 }, + { 0x0013, 0x0096 }, + { 0x0013, 0x0097 }, + { 0x0013, 0x0098 }, + { 0x0013, 0x0099 }, + { 0x0013, 0x009a }, + { 0x0013, 0x009b }, + { 0x0013, 0x009c }, + { 0x0013, 0x009d }, + { 0x0013, 0x009e }, + { 0x0013, 0x009f }, + { 0x0013, 0x00a0 }, + { 0x0012, 0x00fc }, + { 0x0013, 0x00a1 }, + { 0x0013, 0x00a2 }, + { 0x0013, 0x00a3 }, + { 0x0013, 0x00a4 }, + { 0x0013, 0x00a5 }, + { 0x0013, 0x00a6 }, + { 0x0013, 0x00a7 }, + { 0x0013, 0x00a8 }, + { 0x0013, 0x00a9 }, + { 0x0013, 0x00aa }, + { 0x0013, 0x00ab }, + { 0x0013, 0x00ac }, + { 0x0013, 0x00ad }, + { 0x0013, 0x00ae }, + { 0x0013, 0x00af }, + { 0x0013, 0x00b0 }, + { 0x0013, 0x00b1 }, + { 0x0013, 0x00b2 }, + { 0x0013, 0x00b3 }, + { 0x0013, 0x00b4 }, + { 0x0013, 0x00b5 }, + { 0x0013, 0x00b6 }, + { 0x0013, 0x00b7 }, + { 0x0013, 0x00b8 }, + { 0x0013, 0x00b9 }, + { 0x0013, 0x00ba }, + { 0x0013, 0x00bb }, + { 0x0013, 0x00bc }, + { 0x0013, 0x00bd }, + { 0x0013, 0x00be }, + { 0x0013, 0x00bf }, + { 0x0013, 0x00c0 }, + { 0x0013, 0x00c1 }, + { 0x0013, 0x00c2 }, + { 0x0013, 0x00c3 }, + { 0x0013, 0x00c4 }, + { 0x0013, 0x00c5 }, + { 0x0013, 0x00c6 }, + { 0x0013, 0x00c7 }, + { 0x0013, 0x00c8 }, + { 0x0013, 0x00c9 }, + { 0x0013, 0x00ca }, + { 0x0013, 0x00cb }, + { 0x0013, 0x00cc }, + { 0x0013, 0x00cd }, + { 0x0013, 0x00ce }, + { 0x0013, 0x00cf }, + { 0x0013, 0x00d0 }, + { 0x0013, 0x00d1 }, + { 0x0013, 0x00d2 }, + { 0x0013, 0x00d3 }, + { 0x0013, 0x00d4 }, + { 0x0013, 0x00d5 }, + { 0x0013, 0x00d6 }, + { 0x0013, 0x00d7 }, + { 0x0013, 0x00d8 }, + { 0x0013, 0x00d9 }, + { 0x0013, 0x00da }, + { 0x0013, 0x00db }, + { 0x0013, 0x00dc }, + { 0x0013, 0x00dd }, + { 0x0013, 0x00de }, + { 0x0013, 0x00df }, + { 0x0013, 0x00e0 }, + { 0x0013, 0x00e1 }, + { 0x0013, 0x00e2 }, + { 0x0013, 0x00e3 }, + { 0x0013, 0x00e4 }, + { 0x0013, 0x00e5 }, + { 0x0013, 0x00e6 }, + { 0x0013, 0x00e7 }, + { 0x0013, 0x00e8 }, + { 0x0013, 0x00e9 }, + { 0x0013, 0x00ea }, + { 0x0013, 0x00eb }, + { 0x0013, 0x00ec }, + { 0x0013, 0x00ed }, + { 0x0013, 0x00ee }, + { 0x0013, 0x00ef }, + { 0x0013, 0x00f0 }, + { 0x0013, 0x00f1 }, + { 0x0013, 0x00f2 }, + { 0x0013, 0x00f3 }, + { 0x0013, 0x00f4 }, + { 0x0013, 0x00f5 }, + { 0x0013, 0x00f6 }, + { 0x0013, 0x00f7 }, + { 0x0013, 0x00f8 }, + { 0x0013, 0x00f9 }, + { 0x0013, 0x00fa }, + { 0x0013, 0x00fb }, + { 0x0013, 0x00fc }, + { 0x0013, 0x00fd }, + { 0x0013, 0x00fe }, + { 0x0013, 0x00ff }, + { 0x0013, 0x0100 }, + { 0x0013, 0x0101 }, + { 0x0013, 0x0102 }, + { 0x0013, 0x0103 }, + { 0x0013, 0x0104 }, + { 0x0013, 0x0105 }, + { 0x0013, 0x0106 }, + { 0x0013, 0x0107 }, + { 0x0013, 0x0108 }, + { 0x0013, 0x0109 }, + { 0x0013, 0x010a }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0013, 0x010f }, + { 0x0013, 0x0110 }, + { 0x0013, 0x0111 }, + { 0x0013, 0x0112 }, + { 0x0013, 0x0113 }, + { 0x0013, 0x0114 }, + { 0x0013, 0x0115 }, + { 0x0013, 0x0116 }, + { 0x0013, 0x0117 }, + { 0x0013, 0x0118 }, + { 0x0013, 0x0119 }, + { 0x0013, 0x011a }, + { 0x0013, 0x011b }, + { 0x0013, 0x011c }, + { 0x0013, 0x011d }, + { 0x0013, 0x011e }, + { 0x0013, 0x011f }, + { 0x0013, 0x0120 }, + { 0x0013, 0x0121 }, + { 0x0013, 0x0122 }, + { 0x0013, 0x0123 }, + { 0x0013, 0x0124 }, + { 0x0013, 0x0125 }, + { 0x0013, 0x0126 }, + { 0x0013, 0x0127 }, + { 0x0013, 0x0128 }, + { 0x0013, 0x0129 }, + { 0x0013, 0x012a }, + { 0x0013, 0x012b }, + { 0x0013, 0x012c }, + { 0x0013, 0x012d }, + { 0x0013, 0x012e }, + { 0x0013, 0x012f }, + { 0x0013, 0x0130 }, + { 0x0013, 0x0131 }, + { 0x0013, 0x0132 }, + { 0x0013, 0x0133 }, + { 0x0013, 0x0134 }, + { 0x0013, 0x0135 }, + { 0x0013, 0x0136 }, + { 0x0013, 0x0137 }, + { 0x0013, 0x0138 }, + { 0x0013, 0x0139 }, + { 0x0013, 0x013a }, + { 0x0013, 0x013b }, + { 0x0013, 0x013c }, + { 0x0013, 0x013d }, + { 0x0013, 0x013e }, + { 0x0013, 0x013f }, + { 0x0013, 0x0140 }, + { 0x0013, 0x0141 }, + { 0x0013, 0x0142 }, + { 0x0013, 0x0143 }, + { 0x0013, 0x0144 }, + { 0x0013, 0x0145 }, + { 0x0013, 0x0146 }, + { 0x0013, 0x0147 }, + { 0x0013, 0x0148 }, + { 0x0013, 0x0149 }, + { 0x0013, 0x014a }, + { 0x0013, 0x014b }, + { 0x0013, 0x014c }, + { 0x0013, 0x014d }, + { 0x0013, 0x014e }, + { 0x0013, 0x014f }, + { 0x0013, 0x0150 }, + { 0x0013, 0x0151 }, + { 0x0013, 0x0152 }, + { 0x0013, 0x0153 }, + { 0x0013, 0x0154 }, + { 0x0013, 0x0155 }, + { 0x0013, 0x0156 }, + { 0x0013, 0x0157 }, + { 0x0013, 0x0158 }, + { 0x0013, 0x0159 }, + { 0x0013, 0x015a }, + { 0x0013, 0x015b }, + { 0x0013, 0x015c }, + { 0x0013, 0x015d }, + { 0x0013, 0x015e }, + { 0x0013, 0x015f }, + { 0x0013, 0x0160 }, + { 0x0013, 0x0161 }, + { 0x0013, 0x0162 }, + { 0x0013, 0x0163 }, + { 0x0013, 0x0164 }, + { 0x0013, 0x0165 }, + { 0x0013, 0x0166 }, + { 0x0013, 0x0167 }, + { 0x0013, 0x0168 }, + { 0x0013, 0x0169 }, + { 0x0013, 0x016a }, + { 0x0013, 0x016b }, + { 0x0013, 0x016c }, + { 0x0013, 0x016d }, + { 0x0013, 0x016e }, + { 0x0013, 0x016f }, + { 0x0013, 0x0170 }, + { 0x0013, 0x0171 }, + { 0x0013, 0x0172 }, + { 0x0013, 0x0173 }, + { 0x0013, 0x0174 }, + { 0x0013, 0x0175 }, + { 0x0013, 0x0176 }, + { 0x0013, 0x0177 }, + { 0x0013, 0x0178 }, + { 0x0013, 0x0179 }, + { 0x0013, 0x017a }, + { 0x0013, 0x017b }, + { 0x0013, 0x017c }, + { 0x0013, 0x017d }, + { 0x0013, 0x017e }, + { 0x0013, 0x017f }, + { 0x0013, 0x0180 }, + { 0x0013, 0x0181 }, + { 0x0013, 0x0182 }, + { 0x0013, 0x0183 }, + { 0x0013, 0x0184 }, + { 0x0013, 0x0185 }, + { 0x0013, 0x0186 }, + { 0x0013, 0x0187 }, + { 0x0013, 0x0188 }, + { 0x0013, 0x0189 }, + { 0x0013, 0x018a }, + { 0x0013, 0x018b }, + { 0x0013, 0x018c }, + { 0x0013, 0x018d }, + { 0x0013, 0x018e }, + { 0x0013, 0x018f }, + { 0x0013, 0x0190 }, + { 0x0013, 0x0191 }, + { 0x0013, 0x0192 }, + { 0x0013, 0x0193 }, + { 0x0013, 0x0194 }, + { 0x0013, 0x0195 }, + { 0x0013, 0x0196 }, + { 0x0013, 0x0197 }, + { 0x0013, 0x0198 }, + { 0x0013, 0x0199 }, + { 0x0013, 0x019a }, + { 0x0013, 0x019b }, + { 0x0013, 0x019c }, + { 0x0013, 0x019d }, + { 0x0013, 0x019e }, + { 0x0013, 0x019f }, + { 0x0013, 0x01a0 }, + { 0x0013, 0x01a1 }, + { 0x0013, 0x01a2 }, + { 0x0013, 0x01a3 }, + { 0x0013, 0x01a4 }, + { 0x0013, 0x01a5 }, + { 0x0013, 0x01a6 }, + { 0x0013, 0x01a7 }, + { 0x0013, 0x01a8 }, + { 0x0013, 0x01a9 }, + { 0x0013, 0x01aa }, + { 0x0013, 0x01ab }, + { 0x0013, 0x01ac }, + { 0x0013, 0x01ad }, + { 0x0013, 0x01ae }, + { 0x0013, 0x01af }, + { 0x0013, 0x01b0 }, + { 0x0013, 0x01b1 }, + { 0x0013, 0x01b2 }, + { 0x0013, 0x01b3 }, + { 0x0013, 0x01b4 }, + { 0x0013, 0x01b5 }, + { 0x0013, 0x01b6 }, + { 0x0013, 0x01b7 }, + { 0x0013, 0x01b8 }, + { 0x0013, 0x01b9 }, + { 0x0013, 0x01ba }, + { 0x0013, 0x01bb }, + { 0x0013, 0x01bc }, + { 0x0013, 0x01bd }, + { 0x0013, 0x01be }, + { 0x0013, 0x01bf }, + { 0x0013, 0x01c0 }, + { 0x0013, 0x01c1 }, + { 0x0013, 0x01c2 }, + { 0x0013, 0x01c3 }, + { 0x0013, 0x01c4 }, + { 0x0013, 0x01c5 }, + { 0x0013, 0x01c6 }, + { 0x0013, 0x01c7 }, + { 0x0013, 0x01c8 }, + { 0x0013, 0x01c9 }, + { 0x0013, 0x01ca }, + { 0x0013, 0x01cb }, + { 0x0013, 0x01cc }, + { 0x0013, 0x01cd }, + { 0x0013, 0x01ce }, + { 0x0013, 0x01cf }, + { 0x0013, 0x01d0 }, + { 0x0013, 0x01d1 }, + { 0x0013, 0x01d2 }, + { 0x0013, 0x01d3 }, + { 0x0013, 0x01d4 }, + { 0x0013, 0x01d5 }, + { 0x0013, 0x01d6 }, + { 0x0013, 0x01d7 }, + { 0x0013, 0x01d8 }, + { 0x0013, 0x01d9 }, + { 0x0013, 0x01da }, + { 0x0013, 0x01db }, + { 0x0013, 0x01dc }, + { 0x0013, 0x01dd }, + { 0x0013, 0x01de }, + { 0x0013, 0x01df }, + { 0x0013, 0x01e0 }, + { 0x0013, 0x01e1 }, + { 0x0013, 0x01e2 }, + { 0x0013, 0x01e3 }, + { 0x0013, 0x01e4 }, + { 0x0013, 0x01e5 }, + { 0x0013, 0x01e6 }, + { 0x0013, 0x01e7 }, + { 0x0013, 0x01e8 }, + { 0x0013, 0x01e9 }, + { 0x0013, 0x01ea }, + { 0x0013, 0x01eb }, + { 0x0012, 0x00fd }, + }; + +const uint16_t c_aauiLCLDHuffEnc48[729][2] = + { + { 0x0002, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0006 }, + { 0x0006, 0x0006 }, + { 0x0008, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x000b, 0x000b }, + { 0x000c, 0x000d }, + { 0x000f, 0x0030 }, + { 0x0010, 0x0055 }, + { 0x0012, 0x0136 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0013, 0x000f }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0005, 0x0007 }, + { 0x0006, 0x0007 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0007 }, + { 0x000a, 0x0008 }, + { 0x000c, 0x000e }, + { 0x000d, 0x0012 }, + { 0x000f, 0x0031 }, + { 0x0011, 0x00a0 }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0005, 0x0008 }, + { 0x0004, 0x0005 }, + { 0x0005, 0x0009 }, + { 0x0006, 0x0008 }, + { 0x0007, 0x0008 }, + { 0x0008, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000c, 0x000f }, + { 0x000d, 0x0013 }, + { 0x000f, 0x0032 }, + { 0x0011, 0x00a1 }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0007, 0x0009 }, + { 0x0008, 0x0009 }, + { 0x0009, 0x0008 }, + { 0x000b, 0x000c }, + { 0x000d, 0x0014 }, + { 0x000e, 0x001d }, + { 0x000f, 0x0033 }, + { 0x0012, 0x0137 }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0008, 0x000a }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0008, 0x000b }, + { 0x0009, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000c, 0x0010 }, + { 0x000d, 0x0015 }, + { 0x000f, 0x0034 }, + { 0x0010, 0x0056 }, + { 0x0012, 0x0138 }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0009, 0x000a }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0009, 0x000b }, + { 0x000a, 0x000b }, + { 0x000c, 0x0011 }, + { 0x000d, 0x0016 }, + { 0x000e, 0x001e }, + { 0x0010, 0x0057 }, + { 0x0011, 0x00a2 }, + { 0x0011, 0x00a3 }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x0013, 0x0054 }, + { 0x0013, 0x0055 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x000b, 0x000d }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000b, 0x000e }, + { 0x000c, 0x0012 }, + { 0x000d, 0x0017 }, + { 0x000e, 0x001f }, + { 0x0010, 0x0058 }, + { 0x0012, 0x0139 }, + { 0x0011, 0x00a4 }, + { 0x0012, 0x013a }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0013, 0x0062 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x0013, 0x0066 }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x000c, 0x0013 }, + { 0x000b, 0x000f }, + { 0x000c, 0x0014 }, + { 0x000c, 0x0015 }, + { 0x000d, 0x0018 }, + { 0x000e, 0x0020 }, + { 0x000f, 0x0035 }, + { 0x0012, 0x013b }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x000e, 0x0021 }, + { 0x000d, 0x0019 }, + { 0x000e, 0x0022 }, + { 0x000e, 0x0023 }, + { 0x000f, 0x0036 }, + { 0x0010, 0x0059 }, + { 0x0011, 0x00a5 }, + { 0x0013, 0x0083 }, + { 0x0011, 0x00a6 }, + { 0x0012, 0x013c }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x0013, 0x008b }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0013, 0x008e }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0013, 0x0091 }, + { 0x0013, 0x0092 }, + { 0x0013, 0x0093 }, + { 0x0013, 0x0094 }, + { 0x0010, 0x005a }, + { 0x000f, 0x0037 }, + { 0x000f, 0x0038 }, + { 0x000f, 0x0039 }, + { 0x0010, 0x005b }, + { 0x0010, 0x005c }, + { 0x0013, 0x0095 }, + { 0x0011, 0x00a7 }, + { 0x0013, 0x0096 }, + { 0x0013, 0x0097 }, + { 0x0013, 0x0098 }, + { 0x0013, 0x0099 }, + { 0x0013, 0x009a }, + { 0x0013, 0x009b }, + { 0x0013, 0x009c }, + { 0x0013, 0x009d }, + { 0x0013, 0x009e }, + { 0x0013, 0x009f }, + { 0x0013, 0x00a0 }, + { 0x0013, 0x00a1 }, + { 0x0013, 0x00a2 }, + { 0x0013, 0x00a3 }, + { 0x0013, 0x00a4 }, + { 0x0013, 0x00a5 }, + { 0x0013, 0x00a6 }, + { 0x0013, 0x00a7 }, + { 0x0013, 0x00a8 }, + { 0x0010, 0x005d }, + { 0x0010, 0x005e }, + { 0x0013, 0x00a9 }, + { 0x0010, 0x005f }, + { 0x0013, 0x00aa }, + { 0x0012, 0x013d }, + { 0x0013, 0x00ab }, + { 0x0013, 0x00ac }, + { 0x0013, 0x00ad }, + { 0x0013, 0x00ae }, + { 0x0013, 0x00af }, + { 0x0013, 0x00b0 }, + { 0x0013, 0x00b1 }, + { 0x0013, 0x00b2 }, + { 0x0013, 0x00b3 }, + { 0x0013, 0x00b4 }, + { 0x0013, 0x00b5 }, + { 0x0013, 0x00b6 }, + { 0x0013, 0x00b7 }, + { 0x0013, 0x00b8 }, + { 0x0013, 0x00b9 }, + { 0x0013, 0x00ba }, + { 0x0013, 0x00bb }, + { 0x0013, 0x00bc }, + { 0x0013, 0x00bd }, + { 0x0013, 0x00be }, + { 0x0013, 0x00bf }, + { 0x0013, 0x00c0 }, + { 0x0011, 0x00a8 }, + { 0x0013, 0x00c1 }, + { 0x0011, 0x00a9 }, + { 0x0013, 0x00c2 }, + { 0x0013, 0x00c3 }, + { 0x0013, 0x00c4 }, + { 0x0013, 0x00c5 }, + { 0x0013, 0x00c6 }, + { 0x0013, 0x00c7 }, + { 0x0013, 0x00c8 }, + { 0x0013, 0x00c9 }, + { 0x0013, 0x00ca }, + { 0x0013, 0x00cb }, + { 0x0013, 0x00cc }, + { 0x0013, 0x00cd }, + { 0x0013, 0x00ce }, + { 0x0013, 0x00cf }, + { 0x0013, 0x00d0 }, + { 0x0013, 0x00d1 }, + { 0x0013, 0x00d2 }, + { 0x0013, 0x00d3 }, + { 0x0013, 0x00d4 }, + { 0x0013, 0x00d5 }, + { 0x0013, 0x00d6 }, + { 0x0013, 0x00d7 }, + { 0x0013, 0x00d8 }, + { 0x0013, 0x00d9 }, + { 0x0013, 0x00da }, + { 0x0012, 0x013e }, + { 0x0013, 0x00db }, + { 0x0013, 0x00dc }, + { 0x0013, 0x00dd }, + { 0x0013, 0x00de }, + { 0x0013, 0x00df }, + { 0x0013, 0x00e0 }, + { 0x0013, 0x00e1 }, + { 0x0013, 0x00e2 }, + { 0x0013, 0x00e3 }, + { 0x0013, 0x00e4 }, + { 0x0013, 0x00e5 }, + { 0x0013, 0x00e6 }, + { 0x0013, 0x00e7 }, + { 0x0013, 0x00e8 }, + { 0x0013, 0x00e9 }, + { 0x0013, 0x00ea }, + { 0x0013, 0x00eb }, + { 0x0013, 0x00ec }, + { 0x0013, 0x00ed }, + { 0x0013, 0x00ee }, + { 0x0013, 0x00ef }, + { 0x0013, 0x00f0 }, + { 0x0013, 0x00f1 }, + { 0x0013, 0x00f2 }, + { 0x0013, 0x00f3 }, + { 0x0013, 0x00f4 }, + { 0x0013, 0x00f5 }, + { 0x0013, 0x00f6 }, + { 0x0013, 0x00f7 }, + { 0x0013, 0x00f8 }, + { 0x0013, 0x00f9 }, + { 0x0013, 0x00fa }, + { 0x0013, 0x00fb }, + { 0x0013, 0x00fc }, + { 0x0013, 0x00fd }, + { 0x0013, 0x00fe }, + { 0x0013, 0x00ff }, + { 0x0013, 0x0100 }, + { 0x0013, 0x0101 }, + { 0x0013, 0x0102 }, + { 0x0013, 0x0103 }, + { 0x0013, 0x0104 }, + { 0x0013, 0x0105 }, + { 0x0013, 0x0106 }, + { 0x0013, 0x0107 }, + { 0x0013, 0x0108 }, + { 0x0013, 0x0109 }, + { 0x0013, 0x010a }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0013, 0x010f }, + { 0x0013, 0x0110 }, + { 0x0013, 0x0111 }, + { 0x0013, 0x0112 }, + { 0x0013, 0x0113 }, + { 0x0013, 0x0114 }, + { 0x0013, 0x0115 }, + { 0x0013, 0x0116 }, + { 0x0013, 0x0117 }, + { 0x0013, 0x0118 }, + { 0x0013, 0x0119 }, + { 0x0013, 0x011a }, + { 0x0013, 0x011b }, + { 0x0013, 0x011c }, + { 0x0013, 0x011d }, + { 0x0013, 0x011e }, + { 0x0013, 0x011f }, + { 0x0013, 0x0120 }, + { 0x0013, 0x0121 }, + { 0x0013, 0x0122 }, + { 0x0013, 0x0123 }, + { 0x0013, 0x0124 }, + { 0x0013, 0x0125 }, + { 0x0013, 0x0126 }, + { 0x0013, 0x0127 }, + { 0x0013, 0x0128 }, + { 0x0013, 0x0129 }, + { 0x0013, 0x012a }, + { 0x0013, 0x012b }, + { 0x0013, 0x012c }, + { 0x0013, 0x012d }, + { 0x0013, 0x012e }, + { 0x0013, 0x012f }, + { 0x0013, 0x0130 }, + { 0x0013, 0x0131 }, + { 0x0013, 0x0132 }, + { 0x0013, 0x0133 }, + { 0x0013, 0x0134 }, + { 0x0013, 0x0135 }, + { 0x0013, 0x0136 }, + { 0x0013, 0x0137 }, + { 0x0013, 0x0138 }, + { 0x0013, 0x0139 }, + { 0x0013, 0x013a }, + { 0x0013, 0x013b }, + { 0x0013, 0x013c }, + { 0x0013, 0x013d }, + { 0x0013, 0x013e }, + { 0x0013, 0x013f }, + { 0x0013, 0x0140 }, + { 0x0013, 0x0141 }, + { 0x0013, 0x0142 }, + { 0x0013, 0x0143 }, + { 0x0013, 0x0144 }, + { 0x0013, 0x0145 }, + { 0x0013, 0x0146 }, + { 0x0013, 0x0147 }, + { 0x0013, 0x0148 }, + { 0x0013, 0x0149 }, + { 0x0013, 0x014a }, + { 0x0013, 0x014b }, + { 0x0013, 0x014c }, + { 0x0013, 0x014d }, + { 0x0013, 0x014e }, + { 0x0013, 0x014f }, + { 0x0013, 0x0150 }, + { 0x0013, 0x0151 }, + { 0x0013, 0x0152 }, + { 0x0013, 0x0153 }, + { 0x0013, 0x0154 }, + { 0x0013, 0x0155 }, + { 0x0013, 0x0156 }, + { 0x0013, 0x0157 }, + { 0x0013, 0x0158 }, + { 0x0013, 0x0159 }, + { 0x0013, 0x015a }, + { 0x0013, 0x015b }, + { 0x0013, 0x015c }, + { 0x0013, 0x015d }, + { 0x0013, 0x015e }, + { 0x0013, 0x015f }, + { 0x0013, 0x0160 }, + { 0x0013, 0x0161 }, + { 0x0013, 0x0162 }, + { 0x0013, 0x0163 }, + { 0x0013, 0x0164 }, + { 0x0013, 0x0165 }, + { 0x0013, 0x0166 }, + { 0x0013, 0x0167 }, + { 0x0013, 0x0168 }, + { 0x0013, 0x0169 }, + { 0x0013, 0x016a }, + { 0x0013, 0x016b }, + { 0x0013, 0x016c }, + { 0x0013, 0x016d }, + { 0x0013, 0x016e }, + { 0x0013, 0x016f }, + { 0x0013, 0x0170 }, + { 0x0013, 0x0171 }, + { 0x0013, 0x0172 }, + { 0x0013, 0x0173 }, + { 0x0013, 0x0174 }, + { 0x0013, 0x0175 }, + { 0x0013, 0x0176 }, + { 0x0013, 0x0177 }, + { 0x0013, 0x0178 }, + { 0x0013, 0x0179 }, + { 0x0013, 0x017a }, + { 0x0013, 0x017b }, + { 0x0013, 0x017c }, + { 0x0013, 0x017d }, + { 0x0013, 0x017e }, + { 0x0013, 0x017f }, + { 0x0013, 0x0180 }, + { 0x0013, 0x0181 }, + { 0x0013, 0x0182 }, + { 0x0013, 0x0183 }, + { 0x0013, 0x0184 }, + { 0x0013, 0x0185 }, + { 0x0013, 0x0186 }, + { 0x0013, 0x0187 }, + { 0x0013, 0x0188 }, + { 0x0013, 0x0189 }, + { 0x0013, 0x018a }, + { 0x0013, 0x018b }, + { 0x0013, 0x018c }, + { 0x0013, 0x018d }, + { 0x0013, 0x018e }, + { 0x0013, 0x018f }, + { 0x0013, 0x0190 }, + { 0x0013, 0x0191 }, + { 0x0013, 0x0192 }, + { 0x0013, 0x0193 }, + { 0x0013, 0x0194 }, + { 0x0013, 0x0195 }, + { 0x0013, 0x0196 }, + { 0x0013, 0x0197 }, + { 0x0013, 0x0198 }, + { 0x0013, 0x0199 }, + { 0x0013, 0x019a }, + { 0x0013, 0x019b }, + { 0x0013, 0x019c }, + { 0x0013, 0x019d }, + { 0x0013, 0x019e }, + { 0x0013, 0x019f }, + { 0x0013, 0x01a0 }, + { 0x0013, 0x01a1 }, + { 0x0013, 0x01a2 }, + { 0x0013, 0x01a3 }, + { 0x0013, 0x01a4 }, + { 0x0013, 0x01a5 }, + { 0x0013, 0x01a6 }, + { 0x0013, 0x01a7 }, + { 0x0013, 0x01a8 }, + { 0x0013, 0x01a9 }, + { 0x0013, 0x01aa }, + { 0x0013, 0x01ab }, + { 0x0013, 0x01ac }, + { 0x0013, 0x01ad }, + { 0x0013, 0x01ae }, + { 0x0013, 0x01af }, + { 0x0013, 0x01b0 }, + { 0x0013, 0x01b1 }, + { 0x0013, 0x01b2 }, + { 0x0013, 0x01b3 }, + { 0x0013, 0x01b4 }, + { 0x0013, 0x01b5 }, + { 0x0013, 0x01b6 }, + { 0x0013, 0x01b7 }, + { 0x0013, 0x01b8 }, + { 0x0013, 0x01b9 }, + { 0x0013, 0x01ba }, + { 0x0013, 0x01bb }, + { 0x0013, 0x01bc }, + { 0x0013, 0x01bd }, + { 0x0013, 0x01be }, + { 0x0013, 0x01bf }, + { 0x0013, 0x01c0 }, + { 0x0013, 0x01c1 }, + { 0x0013, 0x01c2 }, + { 0x0013, 0x01c3 }, + { 0x0013, 0x01c4 }, + { 0x0013, 0x01c5 }, + { 0x0013, 0x01c6 }, + { 0x0013, 0x01c7 }, + { 0x0013, 0x01c8 }, + { 0x0013, 0x01c9 }, + { 0x0013, 0x01ca }, + { 0x0013, 0x01cb }, + { 0x0013, 0x01cc }, + { 0x0013, 0x01cd }, + { 0x0013, 0x01ce }, + { 0x0013, 0x01cf }, + { 0x0013, 0x01d0 }, + { 0x0013, 0x01d1 }, + { 0x0013, 0x01d2 }, + { 0x0013, 0x01d3 }, + { 0x0013, 0x01d4 }, + { 0x0013, 0x01d5 }, + { 0x0013, 0x01d6 }, + { 0x0013, 0x01d7 }, + { 0x0013, 0x01d8 }, + { 0x0013, 0x01d9 }, + { 0x0013, 0x01da }, + { 0x0013, 0x01db }, + { 0x0013, 0x01dc }, + { 0x0013, 0x01dd }, + { 0x0013, 0x01de }, + { 0x0013, 0x01df }, + { 0x0013, 0x01e0 }, + { 0x0013, 0x01e1 }, + { 0x0013, 0x01e2 }, + { 0x0013, 0x01e3 }, + { 0x0013, 0x01e4 }, + { 0x0013, 0x01e5 }, + { 0x0013, 0x01e6 }, + { 0x0013, 0x01e7 }, + { 0x0013, 0x01e8 }, + { 0x0013, 0x01e9 }, + { 0x0013, 0x01ea }, + { 0x0013, 0x01eb }, + { 0x0013, 0x01ec }, + { 0x0013, 0x01ed }, + { 0x0013, 0x01ee }, + { 0x0013, 0x01ef }, + { 0x0013, 0x01f0 }, + { 0x0013, 0x01f1 }, + { 0x0013, 0x01f2 }, + { 0x0013, 0x01f3 }, + { 0x0013, 0x01f4 }, + { 0x0013, 0x01f5 }, + { 0x0013, 0x01f6 }, + { 0x0013, 0x01f7 }, + { 0x0013, 0x01f8 }, + { 0x0013, 0x01f9 }, + { 0x0013, 0x01fa }, + { 0x0013, 0x01fb }, + { 0x0013, 0x01fc }, + { 0x0013, 0x01fd }, + { 0x0013, 0x01fe }, + { 0x0013, 0x01ff }, + { 0x0013, 0x0200 }, + { 0x0013, 0x0201 }, + { 0x0013, 0x0202 }, + { 0x0013, 0x0203 }, + { 0x0013, 0x0204 }, + { 0x0013, 0x0205 }, + { 0x0013, 0x0206 }, + { 0x0013, 0x0207 }, + { 0x0013, 0x0208 }, + { 0x0013, 0x0209 }, + { 0x0013, 0x020a }, + { 0x0013, 0x020b }, + { 0x0013, 0x020c }, + { 0x0013, 0x020d }, + { 0x0013, 0x020e }, + { 0x0013, 0x020f }, + { 0x0013, 0x0210 }, + { 0x0013, 0x0211 }, + { 0x0013, 0x0212 }, + { 0x0013, 0x0213 }, + { 0x0013, 0x0214 }, + { 0x0013, 0x0215 }, + { 0x0013, 0x0216 }, + { 0x0013, 0x0217 }, + { 0x0013, 0x0218 }, + { 0x0013, 0x0219 }, + { 0x0013, 0x021a }, + { 0x0013, 0x021b }, + { 0x0013, 0x021c }, + { 0x0013, 0x021d }, + { 0x0013, 0x021e }, + { 0x0013, 0x021f }, + { 0x0013, 0x0220 }, + { 0x0013, 0x0221 }, + { 0x0013, 0x0222 }, + { 0x0013, 0x0223 }, + { 0x0013, 0x0224 }, + { 0x0013, 0x0225 }, + { 0x0013, 0x0226 }, + { 0x0013, 0x0227 }, + { 0x0013, 0x0228 }, + { 0x0013, 0x0229 }, + { 0x0013, 0x022a }, + { 0x0013, 0x022b }, + { 0x0013, 0x022c }, + { 0x0013, 0x022d }, + { 0x0013, 0x022e }, + { 0x0013, 0x022f }, + { 0x0013, 0x0230 }, + { 0x0013, 0x0231 }, + { 0x0013, 0x0232 }, + { 0x0013, 0x0233 }, + { 0x0013, 0x0234 }, + { 0x0013, 0x0235 }, + { 0x0013, 0x0236 }, + { 0x0013, 0x0237 }, + { 0x0013, 0x0238 }, + { 0x0013, 0x0239 }, + { 0x0013, 0x023a }, + { 0x0013, 0x023b }, + { 0x0013, 0x023c }, + { 0x0013, 0x023d }, + { 0x0013, 0x023e }, + { 0x0013, 0x023f }, + { 0x0013, 0x0240 }, + { 0x0013, 0x0241 }, + { 0x0013, 0x0242 }, + { 0x0013, 0x0243 }, + { 0x0013, 0x0244 }, + { 0x0013, 0x0245 }, + { 0x0013, 0x0246 }, + { 0x0013, 0x0247 }, + { 0x0013, 0x0248 }, + { 0x0013, 0x0249 }, + { 0x0013, 0x024a }, + { 0x0013, 0x024b }, + { 0x0013, 0x024c }, + { 0x0013, 0x024d }, + { 0x0013, 0x024e }, + { 0x0013, 0x024f }, + { 0x0013, 0x0250 }, + { 0x0013, 0x0251 }, + { 0x0013, 0x0252 }, + { 0x0013, 0x0253 }, + { 0x0013, 0x0254 }, + { 0x0013, 0x0255 }, + { 0x0013, 0x0256 }, + { 0x0013, 0x0257 }, + { 0x0013, 0x0258 }, + { 0x0013, 0x0259 }, + { 0x0013, 0x025a }, + { 0x0013, 0x025b }, + { 0x0013, 0x025c }, + { 0x0013, 0x025d }, + { 0x0013, 0x025e }, + { 0x0013, 0x025f }, + { 0x0013, 0x0260 }, + { 0x0013, 0x0261 }, + { 0x0013, 0x0262 }, + { 0x0013, 0x0263 }, + { 0x0013, 0x0264 }, + { 0x0013, 0x0265 }, + { 0x0013, 0x0266 }, + { 0x0013, 0x0267 }, + { 0x0013, 0x0268 }, + { 0x0013, 0x0269 }, + { 0x0013, 0x026a }, + { 0x0013, 0x026b }, + { 0x0012, 0x013f }, + + }; + +const uint16_t c_aauiLCLDHuffEnc49[729][2] = + { + { 0x0002, 0x0003 }, + { 0x0003, 0x0003 }, + { 0x0005, 0x0007 }, + { 0x0007, 0x000a }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0009, 0x0009 }, + { 0x000b, 0x000d }, + { 0x000d, 0x0014 }, + { 0x000d, 0x0015 }, + { 0x0010, 0x0052 }, + { 0x0011, 0x0098 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0005, 0x0008 }, + { 0x0006, 0x000a }, + { 0x0007, 0x000b }, + { 0x0008, 0x000b }, + { 0x0008, 0x000c }, + { 0x000a, 0x000a }, + { 0x000b, 0x000e }, + { 0x000d, 0x0016 }, + { 0x000f, 0x0031 }, + { 0x0010, 0x0053 }, + { 0x0012, 0x012a }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0006, 0x000b }, + { 0x0007, 0x000c }, + { 0x0008, 0x000d }, + { 0x0009, 0x000a }, + { 0x000a, 0x000b }, + { 0x000c, 0x000f }, + { 0x000d, 0x0017 }, + { 0x000f, 0x0032 }, + { 0x0010, 0x0054 }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + { 0x0013, 0x0028 }, + { 0x0013, 0x0029 }, + { 0x0013, 0x002a }, + { 0x0013, 0x002b }, + { 0x0007, 0x000d }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0008, 0x000e }, + { 0x0009, 0x000b }, + { 0x000b, 0x000f }, + { 0x000c, 0x0010 }, + { 0x000e, 0x001d }, + { 0x000f, 0x0033 }, + { 0x0011, 0x0099 }, + { 0x0013, 0x002c }, + { 0x0013, 0x002d }, + { 0x0013, 0x002e }, + { 0x0013, 0x002f }, + { 0x0013, 0x0030 }, + { 0x0013, 0x0031 }, + { 0x0013, 0x0032 }, + { 0x0013, 0x0033 }, + { 0x0013, 0x0034 }, + { 0x0013, 0x0035 }, + { 0x0013, 0x0036 }, + { 0x0013, 0x0037 }, + { 0x0013, 0x0038 }, + { 0x0013, 0x0039 }, + { 0x0013, 0x003a }, + { 0x0008, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0007, 0x0012 }, + { 0x0008, 0x0010 }, + { 0x0009, 0x000c }, + { 0x000a, 0x000c }, + { 0x000c, 0x0011 }, + { 0x000d, 0x0018 }, + { 0x000e, 0x001e }, + { 0x0011, 0x009a }, + { 0x0011, 0x009b }, + { 0x0013, 0x003b }, + { 0x0013, 0x003c }, + { 0x0013, 0x003d }, + { 0x0013, 0x003e }, + { 0x0013, 0x003f }, + { 0x0013, 0x0040 }, + { 0x0013, 0x0041 }, + { 0x0013, 0x0042 }, + { 0x0013, 0x0043 }, + { 0x0013, 0x0044 }, + { 0x0013, 0x0045 }, + { 0x0013, 0x0046 }, + { 0x0013, 0x0047 }, + { 0x0013, 0x0048 }, + { 0x0013, 0x0049 }, + { 0x0008, 0x0011 }, + { 0x0007, 0x0013 }, + { 0x0008, 0x0012 }, + { 0x0008, 0x0013 }, + { 0x0009, 0x000d }, + { 0x000a, 0x000d }, + { 0x000b, 0x0010 }, + { 0x000c, 0x0012 }, + { 0x000e, 0x001f }, + { 0x000e, 0x0020 }, + { 0x0010, 0x0055 }, + { 0x0011, 0x009c }, + { 0x0013, 0x004a }, + { 0x0013, 0x004b }, + { 0x0013, 0x004c }, + { 0x0013, 0x004d }, + { 0x0013, 0x004e }, + { 0x0013, 0x004f }, + { 0x0013, 0x0050 }, + { 0x0013, 0x0051 }, + { 0x0013, 0x0052 }, + { 0x0013, 0x0053 }, + { 0x0013, 0x0054 }, + { 0x0013, 0x0055 }, + { 0x0013, 0x0056 }, + { 0x0013, 0x0057 }, + { 0x0013, 0x0058 }, + { 0x0009, 0x000e }, + { 0x0009, 0x000f }, + { 0x0009, 0x0010 }, + { 0x0009, 0x0011 }, + { 0x000a, 0x000e }, + { 0x000b, 0x0011 }, + { 0x000c, 0x0013 }, + { 0x000d, 0x0019 }, + { 0x000e, 0x0021 }, + { 0x0010, 0x0056 }, + { 0x0010, 0x0057 }, + { 0x0013, 0x0059 }, + { 0x0013, 0x005a }, + { 0x0013, 0x005b }, + { 0x0013, 0x005c }, + { 0x0013, 0x005d }, + { 0x0013, 0x005e }, + { 0x0013, 0x005f }, + { 0x0013, 0x0060 }, + { 0x0013, 0x0061 }, + { 0x0013, 0x0062 }, + { 0x0013, 0x0063 }, + { 0x0013, 0x0064 }, + { 0x0013, 0x0065 }, + { 0x0013, 0x0066 }, + { 0x0013, 0x0067 }, + { 0x0013, 0x0068 }, + { 0x000b, 0x0012 }, + { 0x000a, 0x000f }, + { 0x000a, 0x0010 }, + { 0x000a, 0x0011 }, + { 0x000c, 0x0014 }, + { 0x000c, 0x0015 }, + { 0x000d, 0x001a }, + { 0x000e, 0x0022 }, + { 0x0010, 0x0058 }, + { 0x0010, 0x0059 }, + { 0x0013, 0x0069 }, + { 0x0013, 0x006a }, + { 0x0013, 0x006b }, + { 0x0013, 0x006c }, + { 0x0013, 0x006d }, + { 0x0013, 0x006e }, + { 0x0013, 0x006f }, + { 0x0013, 0x0070 }, + { 0x0013, 0x0071 }, + { 0x0013, 0x0072 }, + { 0x0013, 0x0073 }, + { 0x0013, 0x0074 }, + { 0x0013, 0x0075 }, + { 0x0013, 0x0076 }, + { 0x0013, 0x0077 }, + { 0x0013, 0x0078 }, + { 0x0013, 0x0079 }, + { 0x000c, 0x0016 }, + { 0x000b, 0x0013 }, + { 0x000c, 0x0017 }, + { 0x000c, 0x0018 }, + { 0x000c, 0x0019 }, + { 0x000e, 0x0023 }, + { 0x000e, 0x0024 }, + { 0x000f, 0x0034 }, + { 0x0010, 0x005a }, + { 0x0011, 0x009d }, + { 0x0013, 0x007a }, + { 0x0013, 0x007b }, + { 0x0013, 0x007c }, + { 0x0013, 0x007d }, + { 0x0013, 0x007e }, + { 0x0013, 0x007f }, + { 0x0013, 0x0080 }, + { 0x0013, 0x0081 }, + { 0x0013, 0x0082 }, + { 0x0013, 0x0083 }, + { 0x0013, 0x0084 }, + { 0x0013, 0x0085 }, + { 0x0013, 0x0086 }, + { 0x0013, 0x0087 }, + { 0x0013, 0x0088 }, + { 0x0013, 0x0089 }, + { 0x0013, 0x008a }, + { 0x000e, 0x0025 }, + { 0x000d, 0x001b }, + { 0x000d, 0x001c }, + { 0x000d, 0x001d }, + { 0x000e, 0x0026 }, + { 0x000f, 0x0035 }, + { 0x0010, 0x005b }, + { 0x0011, 0x009e }, + { 0x0011, 0x009f }, + { 0x0012, 0x012b }, + { 0x0013, 0x008b }, + { 0x0013, 0x008c }, + { 0x0013, 0x008d }, + { 0x0013, 0x008e }, + { 0x0013, 0x008f }, + { 0x0013, 0x0090 }, + { 0x0013, 0x0091 }, + { 0x0013, 0x0092 }, + { 0x0013, 0x0093 }, + { 0x0013, 0x0094 }, + { 0x0013, 0x0095 }, + { 0x0013, 0x0096 }, + { 0x0013, 0x0097 }, + { 0x0013, 0x0098 }, + { 0x0013, 0x0099 }, + { 0x0013, 0x009a }, + { 0x0013, 0x009b }, + { 0x0010, 0x005c }, + { 0x000f, 0x0036 }, + { 0x000e, 0x0027 }, + { 0x000f, 0x0037 }, + { 0x000f, 0x0038 }, + { 0x0010, 0x005d }, + { 0x0011, 0x00a0 }, + { 0x0013, 0x009c }, + { 0x0012, 0x012c }, + { 0x0013, 0x009d }, + { 0x0013, 0x009e }, + { 0x0013, 0x009f }, + { 0x0013, 0x00a0 }, + { 0x0013, 0x00a1 }, + { 0x0013, 0x00a2 }, + { 0x0013, 0x00a3 }, + { 0x0013, 0x00a4 }, + { 0x0013, 0x00a5 }, + { 0x0013, 0x00a6 }, + { 0x0013, 0x00a7 }, + { 0x0013, 0x00a8 }, + { 0x0013, 0x00a9 }, + { 0x0013, 0x00aa }, + { 0x0013, 0x00ab }, + { 0x0013, 0x00ac }, + { 0x0013, 0x00ad }, + { 0x0013, 0x00ae }, + { 0x0010, 0x005e }, + { 0x000f, 0x0039 }, + { 0x0010, 0x005f }, + { 0x0010, 0x0060 }, + { 0x0011, 0x00a1 }, + { 0x0010, 0x0061 }, + { 0x0013, 0x00af }, + { 0x0013, 0x00b0 }, + { 0x0012, 0x012d }, + { 0x0013, 0x00b1 }, + { 0x0013, 0x00b2 }, + { 0x0013, 0x00b3 }, + { 0x0013, 0x00b4 }, + { 0x0013, 0x00b5 }, + { 0x0013, 0x00b6 }, + { 0x0013, 0x00b7 }, + { 0x0013, 0x00b8 }, + { 0x0013, 0x00b9 }, + { 0x0013, 0x00ba }, + { 0x0013, 0x00bb }, + { 0x0013, 0x00bc }, + { 0x0013, 0x00bd }, + { 0x0013, 0x00be }, + { 0x0013, 0x00bf }, + { 0x0013, 0x00c0 }, + { 0x0013, 0x00c1 }, + { 0x0013, 0x00c2 }, + { 0x0012, 0x012e }, + { 0x0011, 0x00a2 }, + { 0x0011, 0x00a3 }, + { 0x0013, 0x00c3 }, + { 0x0013, 0x00c4 }, + { 0x0013, 0x00c5 }, + { 0x0013, 0x00c6 }, + { 0x0013, 0x00c7 }, + { 0x0013, 0x00c8 }, + { 0x0013, 0x00c9 }, + { 0x0013, 0x00ca }, + { 0x0013, 0x00cb }, + { 0x0013, 0x00cc }, + { 0x0013, 0x00cd }, + { 0x0013, 0x00ce }, + { 0x0013, 0x00cf }, + { 0x0013, 0x00d0 }, + { 0x0013, 0x00d1 }, + { 0x0013, 0x00d2 }, + { 0x0013, 0x00d3 }, + { 0x0013, 0x00d4 }, + { 0x0013, 0x00d5 }, + { 0x0013, 0x00d6 }, + { 0x0013, 0x00d7 }, + { 0x0013, 0x00d8 }, + { 0x0013, 0x00d9 }, + { 0x0013, 0x00da }, + { 0x0013, 0x00db }, + { 0x0013, 0x00dc }, + { 0x0013, 0x00dd }, + { 0x0013, 0x00de }, + { 0x0013, 0x00df }, + { 0x0012, 0x012f }, + { 0x0013, 0x00e0 }, + { 0x0013, 0x00e1 }, + { 0x0013, 0x00e2 }, + { 0x0013, 0x00e3 }, + { 0x0013, 0x00e4 }, + { 0x0013, 0x00e5 }, + { 0x0013, 0x00e6 }, + { 0x0013, 0x00e7 }, + { 0x0013, 0x00e8 }, + { 0x0013, 0x00e9 }, + { 0x0013, 0x00ea }, + { 0x0013, 0x00eb }, + { 0x0013, 0x00ec }, + { 0x0013, 0x00ed }, + { 0x0013, 0x00ee }, + { 0x0013, 0x00ef }, + { 0x0013, 0x00f0 }, + { 0x0013, 0x00f1 }, + { 0x0013, 0x00f2 }, + { 0x0013, 0x00f3 }, + { 0x0013, 0x00f4 }, + { 0x0013, 0x00f5 }, + { 0x0013, 0x00f6 }, + { 0x0013, 0x00f7 }, + { 0x0013, 0x00f8 }, + { 0x0013, 0x00f9 }, + { 0x0013, 0x00fa }, + { 0x0013, 0x00fb }, + { 0x0013, 0x00fc }, + { 0x0013, 0x00fd }, + { 0x0013, 0x00fe }, + { 0x0013, 0x00ff }, + { 0x0013, 0x0100 }, + { 0x0013, 0x0101 }, + { 0x0013, 0x0102 }, + { 0x0013, 0x0103 }, + { 0x0013, 0x0104 }, + { 0x0013, 0x0105 }, + { 0x0013, 0x0106 }, + { 0x0013, 0x0107 }, + { 0x0013, 0x0108 }, + { 0x0013, 0x0109 }, + { 0x0013, 0x010a }, + { 0x0013, 0x010b }, + { 0x0013, 0x010c }, + { 0x0013, 0x010d }, + { 0x0013, 0x010e }, + { 0x0013, 0x010f }, + { 0x0013, 0x0110 }, + { 0x0013, 0x0111 }, + { 0x0013, 0x0112 }, + { 0x0013, 0x0113 }, + { 0x0013, 0x0114 }, + { 0x0013, 0x0115 }, + { 0x0013, 0x0116 }, + { 0x0013, 0x0117 }, + { 0x0013, 0x0118 }, + { 0x0013, 0x0119 }, + { 0x0013, 0x011a }, + { 0x0013, 0x011b }, + { 0x0013, 0x011c }, + { 0x0013, 0x011d }, + { 0x0013, 0x011e }, + { 0x0013, 0x011f }, + { 0x0013, 0x0120 }, + { 0x0013, 0x0121 }, + { 0x0013, 0x0122 }, + { 0x0013, 0x0123 }, + { 0x0013, 0x0124 }, + { 0x0013, 0x0125 }, + { 0x0013, 0x0126 }, + { 0x0013, 0x0127 }, + { 0x0013, 0x0128 }, + { 0x0013, 0x0129 }, + { 0x0013, 0x012a }, + { 0x0013, 0x012b }, + { 0x0013, 0x012c }, + { 0x0013, 0x012d }, + { 0x0013, 0x012e }, + { 0x0013, 0x012f }, + { 0x0013, 0x0130 }, + { 0x0013, 0x0131 }, + { 0x0013, 0x0132 }, + { 0x0013, 0x0133 }, + { 0x0013, 0x0134 }, + { 0x0013, 0x0135 }, + { 0x0013, 0x0136 }, + { 0x0013, 0x0137 }, + { 0x0013, 0x0138 }, + { 0x0013, 0x0139 }, + { 0x0013, 0x013a }, + { 0x0013, 0x013b }, + { 0x0013, 0x013c }, + { 0x0013, 0x013d }, + { 0x0013, 0x013e }, + { 0x0013, 0x013f }, + { 0x0013, 0x0140 }, + { 0x0013, 0x0141 }, + { 0x0013, 0x0142 }, + { 0x0013, 0x0143 }, + { 0x0013, 0x0144 }, + { 0x0013, 0x0145 }, + { 0x0013, 0x0146 }, + { 0x0013, 0x0147 }, + { 0x0013, 0x0148 }, + { 0x0013, 0x0149 }, + { 0x0013, 0x014a }, + { 0x0013, 0x014b }, + { 0x0013, 0x014c }, + { 0x0013, 0x014d }, + { 0x0013, 0x014e }, + { 0x0013, 0x014f }, + { 0x0013, 0x0150 }, + { 0x0013, 0x0151 }, + { 0x0013, 0x0152 }, + { 0x0013, 0x0153 }, + { 0x0013, 0x0154 }, + { 0x0013, 0x0155 }, + { 0x0013, 0x0156 }, + { 0x0013, 0x0157 }, + { 0x0013, 0x0158 }, + { 0x0013, 0x0159 }, + { 0x0013, 0x015a }, + { 0x0013, 0x015b }, + { 0x0013, 0x015c }, + { 0x0013, 0x015d }, + { 0x0013, 0x015e }, + { 0x0013, 0x015f }, + { 0x0013, 0x0160 }, + { 0x0013, 0x0161 }, + { 0x0013, 0x0162 }, + { 0x0013, 0x0163 }, + { 0x0013, 0x0164 }, + { 0x0013, 0x0165 }, + { 0x0013, 0x0166 }, + { 0x0013, 0x0167 }, + { 0x0013, 0x0168 }, + { 0x0013, 0x0169 }, + { 0x0013, 0x016a }, + { 0x0013, 0x016b }, + { 0x0013, 0x016c }, + { 0x0013, 0x016d }, + { 0x0013, 0x016e }, + { 0x0013, 0x016f }, + { 0x0013, 0x0170 }, + { 0x0013, 0x0171 }, + { 0x0013, 0x0172 }, + { 0x0013, 0x0173 }, + { 0x0013, 0x0174 }, + { 0x0013, 0x0175 }, + { 0x0013, 0x0176 }, + { 0x0013, 0x0177 }, + { 0x0013, 0x0178 }, + { 0x0013, 0x0179 }, + { 0x0013, 0x017a }, + { 0x0013, 0x017b }, + { 0x0013, 0x017c }, + { 0x0013, 0x017d }, + { 0x0013, 0x017e }, + { 0x0013, 0x017f }, + { 0x0013, 0x0180 }, + { 0x0013, 0x0181 }, + { 0x0013, 0x0182 }, + { 0x0013, 0x0183 }, + { 0x0013, 0x0184 }, + { 0x0013, 0x0185 }, + { 0x0013, 0x0186 }, + { 0x0013, 0x0187 }, + { 0x0013, 0x0188 }, + { 0x0013, 0x0189 }, + { 0x0013, 0x018a }, + { 0x0013, 0x018b }, + { 0x0013, 0x018c }, + { 0x0013, 0x018d }, + { 0x0013, 0x018e }, + { 0x0013, 0x018f }, + { 0x0013, 0x0190 }, + { 0x0013, 0x0191 }, + { 0x0013, 0x0192 }, + { 0x0013, 0x0193 }, + { 0x0013, 0x0194 }, + { 0x0013, 0x0195 }, + { 0x0013, 0x0196 }, + { 0x0013, 0x0197 }, + { 0x0013, 0x0198 }, + { 0x0013, 0x0199 }, + { 0x0013, 0x019a }, + { 0x0013, 0x019b }, + { 0x0013, 0x019c }, + { 0x0013, 0x019d }, + { 0x0013, 0x019e }, + { 0x0013, 0x019f }, + { 0x0013, 0x01a0 }, + { 0x0013, 0x01a1 }, + { 0x0013, 0x01a2 }, + { 0x0013, 0x01a3 }, + { 0x0013, 0x01a4 }, + { 0x0013, 0x01a5 }, + { 0x0013, 0x01a6 }, + { 0x0013, 0x01a7 }, + { 0x0013, 0x01a8 }, + { 0x0013, 0x01a9 }, + { 0x0013, 0x01aa }, + { 0x0013, 0x01ab }, + { 0x0013, 0x01ac }, + { 0x0013, 0x01ad }, + { 0x0013, 0x01ae }, + { 0x0013, 0x01af }, + { 0x0013, 0x01b0 }, + { 0x0013, 0x01b1 }, + { 0x0013, 0x01b2 }, + { 0x0013, 0x01b3 }, + { 0x0013, 0x01b4 }, + { 0x0013, 0x01b5 }, + { 0x0013, 0x01b6 }, + { 0x0013, 0x01b7 }, + { 0x0013, 0x01b8 }, + { 0x0013, 0x01b9 }, + { 0x0013, 0x01ba }, + { 0x0013, 0x01bb }, + { 0x0013, 0x01bc }, + { 0x0013, 0x01bd }, + { 0x0013, 0x01be }, + { 0x0013, 0x01bf }, + { 0x0013, 0x01c0 }, + { 0x0013, 0x01c1 }, + { 0x0013, 0x01c2 }, + { 0x0013, 0x01c3 }, + { 0x0013, 0x01c4 }, + { 0x0013, 0x01c5 }, + { 0x0013, 0x01c6 }, + { 0x0013, 0x01c7 }, + { 0x0013, 0x01c8 }, + { 0x0013, 0x01c9 }, + { 0x0013, 0x01ca }, + { 0x0013, 0x01cb }, + { 0x0013, 0x01cc }, + { 0x0013, 0x01cd }, + { 0x0013, 0x01ce }, + { 0x0013, 0x01cf }, + { 0x0013, 0x01d0 }, + { 0x0013, 0x01d1 }, + { 0x0013, 0x01d2 }, + { 0x0013, 0x01d3 }, + { 0x0013, 0x01d4 }, + { 0x0013, 0x01d5 }, + { 0x0013, 0x01d6 }, + { 0x0013, 0x01d7 }, + { 0x0013, 0x01d8 }, + { 0x0013, 0x01d9 }, + { 0x0013, 0x01da }, + { 0x0013, 0x01db }, + { 0x0013, 0x01dc }, + { 0x0013, 0x01dd }, + { 0x0013, 0x01de }, + { 0x0013, 0x01df }, + { 0x0013, 0x01e0 }, + { 0x0013, 0x01e1 }, + { 0x0013, 0x01e2 }, + { 0x0013, 0x01e3 }, + { 0x0013, 0x01e4 }, + { 0x0013, 0x01e5 }, + { 0x0013, 0x01e6 }, + { 0x0013, 0x01e7 }, + { 0x0013, 0x01e8 }, + { 0x0013, 0x01e9 }, + { 0x0013, 0x01ea }, + { 0x0013, 0x01eb }, + { 0x0013, 0x01ec }, + { 0x0013, 0x01ed }, + { 0x0013, 0x01ee }, + { 0x0013, 0x01ef }, + { 0x0013, 0x01f0 }, + { 0x0013, 0x01f1 }, + { 0x0013, 0x01f2 }, + { 0x0013, 0x01f3 }, + { 0x0013, 0x01f4 }, + { 0x0013, 0x01f5 }, + { 0x0013, 0x01f6 }, + { 0x0013, 0x01f7 }, + { 0x0013, 0x01f8 }, + { 0x0013, 0x01f9 }, + { 0x0013, 0x01fa }, + { 0x0013, 0x01fb }, + { 0x0013, 0x01fc }, + { 0x0013, 0x01fd }, + { 0x0013, 0x01fe }, + { 0x0013, 0x01ff }, + { 0x0013, 0x0200 }, + { 0x0013, 0x0201 }, + { 0x0013, 0x0202 }, + { 0x0013, 0x0203 }, + { 0x0013, 0x0204 }, + { 0x0013, 0x0205 }, + { 0x0013, 0x0206 }, + { 0x0013, 0x0207 }, + { 0x0013, 0x0208 }, + { 0x0013, 0x0209 }, + { 0x0013, 0x020a }, + { 0x0013, 0x020b }, + { 0x0013, 0x020c }, + { 0x0013, 0x020d }, + { 0x0013, 0x020e }, + { 0x0013, 0x020f }, + { 0x0013, 0x0210 }, + { 0x0013, 0x0211 }, + { 0x0013, 0x0212 }, + { 0x0013, 0x0213 }, + { 0x0013, 0x0214 }, + { 0x0013, 0x0215 }, + { 0x0013, 0x0216 }, + { 0x0013, 0x0217 }, + { 0x0013, 0x0218 }, + { 0x0013, 0x0219 }, + { 0x0013, 0x021a }, + { 0x0013, 0x021b }, + { 0x0013, 0x021c }, + { 0x0013, 0x021d }, + { 0x0013, 0x021e }, + { 0x0013, 0x021f }, + { 0x0013, 0x0220 }, + { 0x0013, 0x0221 }, + { 0x0013, 0x0222 }, + { 0x0013, 0x0223 }, + { 0x0013, 0x0224 }, + { 0x0013, 0x0225 }, + { 0x0013, 0x0226 }, + { 0x0013, 0x0227 }, + { 0x0013, 0x0228 }, + { 0x0013, 0x0229 }, + { 0x0013, 0x022a }, + { 0x0013, 0x022b }, + { 0x0013, 0x022c }, + { 0x0013, 0x022d }, + { 0x0013, 0x022e }, + { 0x0013, 0x022f }, + { 0x0013, 0x0230 }, + { 0x0013, 0x0231 }, + { 0x0013, 0x0232 }, + { 0x0013, 0x0233 }, + { 0x0013, 0x0234 }, + { 0x0013, 0x0235 }, + { 0x0013, 0x0236 }, + { 0x0013, 0x0237 }, + { 0x0013, 0x0238 }, + { 0x0013, 0x0239 }, + { 0x0013, 0x023a }, + { 0x0013, 0x023b }, + { 0x0013, 0x023c }, + { 0x0013, 0x023d }, + { 0x0013, 0x023e }, + { 0x0013, 0x023f }, + { 0x0013, 0x0240 }, + { 0x0013, 0x0241 }, + { 0x0013, 0x0242 }, + { 0x0013, 0x0243 }, + { 0x0013, 0x0244 }, + { 0x0013, 0x0245 }, + { 0x0013, 0x0246 }, + { 0x0013, 0x0247 }, + { 0x0013, 0x0248 }, + { 0x0013, 0x0249 }, + { 0x0013, 0x024a }, + { 0x0013, 0x024b }, + { 0x0013, 0x024c }, + { 0x0013, 0x024d }, + { 0x0013, 0x024e }, + { 0x0013, 0x024f }, + { 0x0013, 0x0250 }, + { 0x0013, 0x0251 }, + { 0x0013, 0x0252 }, + { 0x0013, 0x0253 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc50[28][2] = + { + { 0x0002, 0x0001 }, + { 0x0002, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0001 }, + { 0x0004, 0x0001 }, + { 0x0005, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x000f, 0x0001 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0005 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc51[29][2] = + { + { 0x0002, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0004, 0x0001 }, + { 0x0004, 0x0002 }, + { 0x0004, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0006, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x000d, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc52[32][2] = + { + { 0x0002, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0004, 0x0002 }, + { 0x0004, 0x0003 }, + { 0x0005, 0x0001 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0006, 0x0001 }, + { 0x0007, 0x0001 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000a, 0x0001 }, + { 0x000b, 0x0001 }, + { 0x000c, 0x0001 }, + { 0x000e, 0x0001 }, + { 0x000e, 0x0002 }, + { 0x000e, 0x0003 }, + { 0x000f, 0x0001 }, + { 0x0011, 0x0002 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0003 }, + { 0x0014, 0x0000 }, + { 0x0013, 0x0003 }, + { 0x0014, 0x0001 }, + { 0x0014, 0x0002 }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + }; + +const uint16_t c_aauiLCLDHuffEnc53[37][2] = + { + { 0x0002, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0004, 0x0002 }, + { 0x0004, 0x0003 }, + { 0x0005, 0x0002 }, + { 0x0005, 0x0003 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0007, 0x0001 }, + { 0x0007, 0x0002 }, + { 0x0007, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x0009, 0x0001 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000d, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x000e, 0x0002 }, + { 0x000e, 0x0003 }, + { 0x000f, 0x0002 }, + { 0x000f, 0x0003 }, + { 0x0011, 0x0004 }, + { 0x0010, 0x0003 }, + { 0x0011, 0x0005 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0012, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc54[39][2] = + { + { 0x0002, 0x0002 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0002 }, + { 0x0003, 0x0003 }, + { 0x0004, 0x0003 }, + { 0x0005, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0006, 0x0002 }, + { 0x0006, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0002 }, + { 0x0007, 0x0003 }, + { 0x0008, 0x0001 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000d, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x000e, 0x0002 }, + { 0x000e, 0x0003 }, + { 0x000f, 0x0002 }, + { 0x000f, 0x0003 }, + { 0x0011, 0x0002 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc55[46][2] = + { + { 0x0003, 0x0003 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0004, 0x0003 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0005, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0006, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0002 }, + { 0x0007, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000b, 0x0002 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0002 }, + { 0x000c, 0x0003 }, + { 0x000d, 0x0002 }, + { 0x000d, 0x0003 }, + { 0x000e, 0x0002 }, + { 0x000e, 0x0003 }, + { 0x000f, 0x0003 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0010, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc56[55][2] = + { + { 0x0003, 0x0003 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0004 }, + { 0x0003, 0x0005 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0005, 0x0003 }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0006, 0x0003 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0007, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0008, 0x0002 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0009, 0x0002 }, + { 0x0009, 0x0003 }, + { 0x000a, 0x0002 }, + { 0x000a, 0x0003 }, + { 0x000b, 0x0003 }, + { 0x000c, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000d, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000e, 0x0003 }, + { 0x000e, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x000f, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x0010, 0x0002 }, + { 0x0010, 0x0003 }, + { 0x0010, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x0010, 0x0006 }, + { 0x0010, 0x0007 }, + { 0x0013, 0x0000 }, + { 0x0011, 0x0003 }, + { 0x0012, 0x0005 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc57[65][2] = + { + { 0x0003, 0x0004 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0005 }, + { 0x0004, 0x0004 }, + { 0x0004, 0x0005 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0005, 0x0004 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0007, 0x0003 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0009, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000a, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000b, 0x0003 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000c, 0x0003 }, + { 0x000c, 0x0004 }, + { 0x000d, 0x0003 }, + { 0x000c, 0x0005 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000e, 0x0003 }, + { 0x000e, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x000f, 0x0003 }, + { 0x0010, 0x0003 }, + { 0x000f, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x0010, 0x0004 }, + { 0x0010, 0x0005 }, + { 0x0013, 0x0000 }, + { 0x0011, 0x0005 }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0012, 0x0007 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc58[77][2] = + { + { 0x0004, 0x0005 }, + { 0x0003, 0x0005 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0005, 0x0005 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0006, 0x0004 }, + { 0x0006, 0x0005 }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0007, 0x0004 }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0009, 0x0003 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000a, 0x0003 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x000e, 0x0006 }, + { 0x000e, 0x0007 }, + { 0x000f, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x000f, 0x0006 }, + { 0x0010, 0x0004 }, + { 0x000f, 0x0007 }, + { 0x0010, 0x0005 }, + { 0x0010, 0x0006 }, + { 0x0010, 0x0007 }, + { 0x0013, 0x0000 }, + { 0x0013, 0x0001 }, + { 0x0012, 0x0006 }, + { 0x0011, 0x0007 }, + { 0x0013, 0x0002 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0012, 0x0007 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + { 0x0012, 0x000c }, + { 0x0012, 0x000d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc59[91][2] = + { + { 0x0003, 0x0005 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0006 }, + { 0x0004, 0x0007 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0005, 0x0006 }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0006, 0x0006 }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0007, 0x0005 }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0007, 0x0008 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0008, 0x0003 }, + { 0x0008, 0x0004 }, + { 0x0008, 0x0005 }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000d, 0x0003 }, + { 0x000d, 0x0004 }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000e, 0x0003 }, + { 0x000e, 0x0004 }, + { 0x000e, 0x0005 }, + { 0x000f, 0x0003 }, + { 0x000f, 0x0004 }, + { 0x000f, 0x0005 }, + { 0x0011, 0x0008 }, + { 0x0011, 0x0009 }, + { 0x0013, 0x0000 }, + { 0x0011, 0x000a }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0012, 0x000d }, + { 0x0012, 0x000e }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0011, 0x000b }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0012, 0x000f }, + + }; + +const uint16_t c_aauiLCLDHuffEnc60[109][2] = + { + { 0x0004, 0x0007 }, + { 0x0002, 0x0003 }, + { 0x0003, 0x0005 }, + { 0x0004, 0x0008 }, + { 0x0004, 0x0009 }, + { 0x0005, 0x0007 }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0006, 0x0007 }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0007, 0x0006 }, + { 0x0007, 0x0007 }, + { 0x0007, 0x0008 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0009, 0x0004 }, + { 0x0009, 0x0005 }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000b, 0x0004 }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0004 }, + { 0x000c, 0x0005 }, + { 0x000c, 0x0006 }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000c, 0x0007 }, + { 0x000e, 0x0005 }, + { 0x000e, 0x0006 }, + { 0x000e, 0x0007 }, + { 0x000e, 0x0008 }, + { 0x000f, 0x0005 }, + { 0x000e, 0x0009 }, + { 0x000f, 0x0006 }, + { 0x0010, 0x0006 }, + { 0x000f, 0x0007 }, + { 0x000f, 0x0008 }, + { 0x000f, 0x0009 }, + { 0x0010, 0x0007 }, + { 0x0010, 0x0008 }, + { 0x0010, 0x0009 }, + { 0x0011, 0x000a }, + { 0x0013, 0x0000 }, + { 0x0011, 0x000b }, + { 0x0013, 0x0001 }, + { 0x0013, 0x0002 }, + { 0x0012, 0x0011 }, + { 0x0012, 0x0012 }, + { 0x0013, 0x0003 }, + { 0x0013, 0x0004 }, + { 0x0013, 0x0005 }, + { 0x0013, 0x0006 }, + { 0x0013, 0x0007 }, + { 0x0013, 0x0008 }, + { 0x0013, 0x0009 }, + { 0x0013, 0x000a }, + { 0x0013, 0x000b }, + { 0x0013, 0x000c }, + { 0x0013, 0x000d }, + { 0x0013, 0x000e }, + { 0x0013, 0x000f }, + { 0x0013, 0x0010 }, + { 0x0013, 0x0011 }, + { 0x0013, 0x0012 }, + { 0x0013, 0x0013 }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0012, 0x0013 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc61[129][2] = + { + { 0x0004, 0x0008 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x0009 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0005, 0x0008 }, + { 0x0005, 0x0009 }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0006, 0x0008 }, + { 0x0006, 0x0009 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0007, 0x0008 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0008, 0x0006 }, + { 0x0008, 0x0007 }, + { 0x0008, 0x0008 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0008, 0x000e }, + { 0x0008, 0x000f }, + { 0x0009, 0x0006 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000a, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000b, 0x0005 }, + { 0x000b, 0x0006 }, + { 0x000b, 0x0007 }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000c, 0x0006 }, + { 0x000c, 0x0007 }, + { 0x000c, 0x0008 }, + { 0x000c, 0x0009 }, + { 0x000d, 0x0005 }, + { 0x000d, 0x0006 }, + { 0x000d, 0x0007 }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000d, 0x000a }, + { 0x000e, 0x0008 }, + { 0x000d, 0x000b }, + { 0x000e, 0x0009 }, + { 0x000f, 0x0009 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + { 0x000f, 0x000c }, + { 0x000f, 0x000d }, + { 0x000f, 0x000e }, + { 0x0010, 0x000c }, + { 0x0011, 0x0015 }, + { 0x0010, 0x000d }, + { 0x000f, 0x000f }, + { 0x0010, 0x000e }, + { 0x0010, 0x000f }, + { 0x0012, 0x0000 }, + { 0x0011, 0x0016 }, + { 0x0010, 0x0010 }, + { 0x0010, 0x0011 }, + { 0x0011, 0x0017 }, + { 0x0012, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + { 0x0012, 0x000c }, + { 0x0012, 0x000d }, + { 0x0012, 0x000e }, + { 0x0012, 0x000f }, + { 0x0012, 0x0010 }, + { 0x0012, 0x0011 }, + { 0x0012, 0x0012 }, + { 0x0012, 0x0013 }, + { 0x0012, 0x0014 }, + { 0x0012, 0x0015 }, + { 0x0012, 0x0016 }, + { 0x0012, 0x0017 }, + { 0x0012, 0x0018 }, + { 0x0012, 0x0019 }, + { 0x0012, 0x001a }, + { 0x0012, 0x001b }, + { 0x0012, 0x001c }, + { 0x0012, 0x001d }, + { 0x0012, 0x001e }, + { 0x0012, 0x001f }, + { 0x0012, 0x0020 }, + { 0x0012, 0x0021 }, + { 0x0012, 0x0022 }, + { 0x0012, 0x0023 }, + { 0x0012, 0x0024 }, + { 0x0012, 0x0025 }, + { 0x0012, 0x0026 }, + { 0x0012, 0x0027 }, + { 0x0012, 0x0028 }, + { 0x0012, 0x0029 }, + + }; + +const uint16_t c_aauiLCLDHuffEnc62[153][2] = + { + { 0x0004, 0x0009 }, + { 0x0003, 0x0006 }, + { 0x0003, 0x0007 }, + { 0x0004, 0x000a }, + { 0x0004, 0x000b }, + { 0x0005, 0x000a }, + { 0x0005, 0x000b }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0005, 0x0010 }, + { 0x0005, 0x0011 }, + { 0x0006, 0x000a }, + { 0x0006, 0x000b }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0007, 0x0009 }, + { 0x0007, 0x000a }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0007, 0x0012 }, + { 0x0007, 0x0013 }, + { 0x0008, 0x0009 }, + { 0x0008, 0x000a }, + { 0x0008, 0x000b }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0008, 0x000e }, + { 0x0008, 0x000f }, + { 0x0008, 0x0010 }, + { 0x0008, 0x0011 }, + { 0x0009, 0x0007 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x0009, 0x000c }, + { 0x0009, 0x000d }, + { 0x0009, 0x000e }, + { 0x0009, 0x000f }, + { 0x0009, 0x0010 }, + { 0x0009, 0x0011 }, + { 0x000a, 0x0004 }, + { 0x000a, 0x0005 }, + { 0x000a, 0x0006 }, + { 0x000a, 0x0007 }, + { 0x000a, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000b, 0x0007 }, + { 0x000c, 0x0007 }, + { 0x000c, 0x0008 }, + { 0x000c, 0x0009 }, + { 0x000c, 0x000a }, + { 0x000c, 0x000b }, + { 0x000c, 0x000c }, + { 0x000d, 0x0007 }, + { 0x000c, 0x000d }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000d, 0x000a }, + { 0x000d, 0x000b }, + { 0x000e, 0x0008 }, + { 0x000d, 0x000c }, + { 0x000d, 0x000d }, + { 0x000e, 0x0009 }, + { 0x000e, 0x000a }, + { 0x000e, 0x000b }, + { 0x000e, 0x000c }, + { 0x000f, 0x000c }, + { 0x000e, 0x000d }, + { 0x000f, 0x000d }, + { 0x000f, 0x000e }, + { 0x000f, 0x000f }, + { 0x0010, 0x000f }, + { 0x0010, 0x0010 }, + { 0x0011, 0x0019 }, + { 0x0010, 0x0011 }, + { 0x0010, 0x0012 }, + { 0x0010, 0x0013 }, + { 0x0010, 0x0014 }, + { 0x0010, 0x0015 }, + { 0x0012, 0x0000 }, + { 0x0010, 0x0016 }, + { 0x0011, 0x001a }, + { 0x0010, 0x0017 }, + { 0x0012, 0x0001 }, + { 0x0012, 0x0002 }, + { 0x0012, 0x0003 }, + { 0x0011, 0x001b }, + { 0x0012, 0x0004 }, + { 0x0012, 0x0005 }, + { 0x0012, 0x0006 }, + { 0x0012, 0x0007 }, + { 0x0012, 0x0008 }, + { 0x0012, 0x0009 }, + { 0x0012, 0x000a }, + { 0x0012, 0x000b }, + { 0x0012, 0x000c }, + { 0x0012, 0x000d }, + { 0x0012, 0x000e }, + { 0x0012, 0x000f }, + { 0x0012, 0x0010 }, + { 0x0012, 0x0011 }, + { 0x0012, 0x0012 }, + { 0x0012, 0x0013 }, + { 0x0012, 0x0014 }, + { 0x0012, 0x0015 }, + { 0x0012, 0x0016 }, + { 0x0012, 0x0017 }, + { 0x0012, 0x0018 }, + { 0x0011, 0x001c }, + { 0x0012, 0x0019 }, + { 0x0012, 0x001a }, + { 0x0012, 0x001b }, + { 0x0012, 0x001c }, + { 0x0012, 0x001d }, + { 0x0012, 0x001e }, + { 0x0012, 0x001f }, + { 0x0012, 0x0020 }, + { 0x0012, 0x0021 }, + { 0x0012, 0x0022 }, + { 0x0012, 0x0023 }, + { 0x0012, 0x0024 }, + { 0x0012, 0x0025 }, + { 0x0012, 0x0026 }, + { 0x0012, 0x0027 }, + { 0x0012, 0x0028 }, + { 0x0012, 0x0029 }, + { 0x0012, 0x002a }, + { 0x0012, 0x002b }, + { 0x0012, 0x002c }, + { 0x0012, 0x002d }, + { 0x0012, 0x002e }, + { 0x0012, 0x002f }, + { 0x0012, 0x0030 }, + { 0x0012, 0x0031 }, + { 0x0011, 0x001d }, + + }; + +const uint16_t c_aauiLCLDHuffEnc63[181][2] = + { + { 0x0004, 0x0008 }, + { 0x0003, 0x0005 }, + { 0x0002, 0x0003 }, + { 0x0004, 0x0009 }, + { 0x0005, 0x000c }, + { 0x0005, 0x000d }, + { 0x0005, 0x000e }, + { 0x0005, 0x000f }, + { 0x0006, 0x000c }, + { 0x0006, 0x000d }, + { 0x0006, 0x000e }, + { 0x0006, 0x000f }, + { 0x0006, 0x0010 }, + { 0x0006, 0x0011 }, + { 0x0006, 0x0012 }, + { 0x0006, 0x0013 }, + { 0x0006, 0x0014 }, + { 0x0006, 0x0015 }, + { 0x0006, 0x0016 }, + { 0x0006, 0x0017 }, + { 0x0007, 0x000b }, + { 0x0007, 0x000c }, + { 0x0007, 0x000d }, + { 0x0007, 0x000e }, + { 0x0007, 0x000f }, + { 0x0007, 0x0010 }, + { 0x0007, 0x0011 }, + { 0x0007, 0x0012 }, + { 0x0007, 0x0013 }, + { 0x0007, 0x0014 }, + { 0x0007, 0x0015 }, + { 0x0007, 0x0016 }, + { 0x0007, 0x0017 }, + { 0x0008, 0x000c }, + { 0x0008, 0x000d }, + { 0x0008, 0x000e }, + { 0x0008, 0x000f }, + { 0x0008, 0x0010 }, + { 0x0008, 0x0011 }, + { 0x0008, 0x0012 }, + { 0x0008, 0x0013 }, + { 0x0008, 0x0014 }, + { 0x0008, 0x0015 }, + { 0x0009, 0x0008 }, + { 0x0009, 0x0009 }, + { 0x0009, 0x000a }, + { 0x0009, 0x000b }, + { 0x0009, 0x000c }, + { 0x0009, 0x000d }, + { 0x0009, 0x000e }, + { 0x0009, 0x000f }, + { 0x0009, 0x0010 }, + { 0x0009, 0x0011 }, + { 0x0009, 0x0012 }, + { 0x0009, 0x0013 }, + { 0x0009, 0x0014 }, + { 0x0009, 0x0015 }, + { 0x000a, 0x0007 }, + { 0x0009, 0x0016 }, + { 0x0009, 0x0017 }, + { 0x000a, 0x0008 }, + { 0x000a, 0x0009 }, + { 0x000a, 0x000a }, + { 0x000a, 0x000b }, + { 0x000a, 0x000c }, + { 0x000a, 0x000d }, + { 0x000a, 0x000e }, + { 0x000b, 0x0008 }, + { 0x000b, 0x0009 }, + { 0x000b, 0x000a }, + { 0x000a, 0x000f }, + { 0x000b, 0x000b }, + { 0x000b, 0x000c }, + { 0x000b, 0x000d }, + { 0x000c, 0x0009 }, + { 0x000c, 0x000a }, + { 0x000c, 0x000b }, + { 0x000c, 0x000c }, + { 0x000c, 0x000d }, + { 0x000c, 0x000e }, + { 0x000c, 0x000f }, + { 0x000d, 0x0008 }, + { 0x000d, 0x0009 }, + { 0x000d, 0x000a }, + { 0x000d, 0x000b }, + { 0x000d, 0x000c }, + { 0x000d, 0x000d }, + { 0x000d, 0x000e }, + { 0x000d, 0x000f }, + { 0x000d, 0x0010 }, + { 0x000d, 0x0011 }, + { 0x000e, 0x0007 }, + { 0x000e, 0x0008 }, + { 0x000e, 0x0009 }, + { 0x000e, 0x000a }, + { 0x000e, 0x000b }, + { 0x000e, 0x000c }, + { 0x000e, 0x000d }, + { 0x000e, 0x000e }, + { 0x000e, 0x000f }, + { 0x000f, 0x0008 }, + { 0x000f, 0x0009 }, + { 0x000f, 0x000a }, + { 0x000f, 0x000b }, + { 0x000f, 0x000c }, + { 0x0010, 0x0009 }, + { 0x0010, 0x000a }, + { 0x000f, 0x000d }, + { 0x0010, 0x000b }, + { 0x0010, 0x000c }, + { 0x0010, 0x000d }, + { 0x0011, 0x000e }, + { 0x0011, 0x000f }, + { 0x0010, 0x000e }, + { 0x0011, 0x0010 }, + { 0x0011, 0x0011 }, + { 0x0012, 0x0014 }, + { 0x0014, 0x0000 }, + { 0x0010, 0x000f }, + { 0x0012, 0x0015 }, + { 0x0012, 0x0016 }, + { 0x0014, 0x0001 }, + { 0x0012, 0x0017 }, + { 0x0012, 0x0018 }, + { 0x0012, 0x0019 }, + { 0x0013, 0x0010 }, + { 0x0012, 0x001a }, + { 0x0014, 0x0002 }, + { 0x0012, 0x001b }, + { 0x0014, 0x0003 }, + { 0x0014, 0x0004 }, + { 0x0014, 0x0005 }, + { 0x0013, 0x0011 }, + { 0x0014, 0x0006 }, + { 0x0013, 0x0012 }, + { 0x0014, 0x0007 }, + { 0x0014, 0x0008 }, + { 0x0014, 0x0009 }, + { 0x0014, 0x000a }, + { 0x0014, 0x000b }, + { 0x0014, 0x000c }, + { 0x0014, 0x000d }, + { 0x0014, 0x000e }, + { 0x0013, 0x0013 }, + { 0x0014, 0x000f }, + { 0x0014, 0x0010 }, + { 0x0014, 0x0011 }, + { 0x0014, 0x0012 }, + { 0x0014, 0x0013 }, + { 0x0014, 0x0014 }, + { 0x0014, 0x0015 }, + { 0x0014, 0x0016 }, + { 0x0014, 0x0017 }, + { 0x0014, 0x0018 }, + { 0x0014, 0x0019 }, + { 0x0014, 0x001a }, + { 0x0014, 0x001b }, + { 0x0014, 0x001c }, + { 0x0014, 0x001d }, + { 0x0014, 0x001e }, + { 0x0014, 0x001f }, + { 0x0013, 0x0014 }, + { 0x0013, 0x0015 }, + { 0x0013, 0x0016 }, + { 0x0013, 0x0017 }, + { 0x0013, 0x0018 }, + { 0x0013, 0x0019 }, + { 0x0013, 0x001a }, + { 0x0013, 0x001b }, + { 0x0013, 0x001c }, + { 0x0013, 0x001d }, + { 0x0013, 0x001e }, + { 0x0013, 0x001f }, + { 0x0013, 0x0020 }, + { 0x0013, 0x0021 }, + { 0x0013, 0x0022 }, + { 0x0013, 0x0023 }, + { 0x0013, 0x0024 }, + { 0x0013, 0x0025 }, + { 0x0013, 0x0026 }, + { 0x0013, 0x0027 }, + + }; + +const uint16_t ( *c_apauiHuffEncTabels[2 * ALLOC_TABLE_SIZE] )[2] = + { + NULL, + c_aauiLCLDHuffEnc1, + c_aauiLCLDHuffEnc2, + c_aauiLCLDHuffEnc3, + c_aauiLCLDHuffEnc4, + c_aauiLCLDHuffEnc5, + c_aauiLCLDHuffEnc6, + c_aauiLCLDHuffEnc7, + c_aauiLCLDHuffEnc8, + c_aauiLCLDHuffEnc9, + c_aauiLCLDHuffEnc10, + c_aauiLCLDHuffEnc11, + c_aauiLCLDHuffEnc12, + c_aauiLCLDHuffEnc13, + c_aauiLCLDHuffEnc14, + c_aauiLCLDHuffEnc15, + c_aauiLCLDHuffEnc16, + c_aauiLCLDHuffEnc17, + c_aauiLCLDHuffEnc18, + c_aauiLCLDHuffEnc19, + c_aauiLCLDHuffEnc20, + c_aauiLCLDHuffEnc21, + c_aauiLCLDHuffEnc22, + c_aauiLCLDHuffEnc23, + c_aauiLCLDHuffEnc24, + c_aauiLCLDHuffEnc25, + c_aauiLCLDHuffEnc26, + c_aauiLCLDHuffEnc27, + c_aauiLCLDHuffEnc28, + c_aauiLCLDHuffEnc29, + c_aauiLCLDHuffEnc30, + c_aauiLCLDHuffEnc31, + NULL, + c_aauiLCLDHuffEnc33, + c_aauiLCLDHuffEnc34, + c_aauiLCLDHuffEnc35, + c_aauiLCLDHuffEnc36, + c_aauiLCLDHuffEnc37, + c_aauiLCLDHuffEnc38, + c_aauiLCLDHuffEnc39, + c_aauiLCLDHuffEnc40, + c_aauiLCLDHuffEnc41, + c_aauiLCLDHuffEnc42, + c_aauiLCLDHuffEnc43, + c_aauiLCLDHuffEnc44, + c_aauiLCLDHuffEnc45, + c_aauiLCLDHuffEnc46, + c_aauiLCLDHuffEnc47, + c_aauiLCLDHuffEnc48, + c_aauiLCLDHuffEnc49, + c_aauiLCLDHuffEnc50, + c_aauiLCLDHuffEnc51, + c_aauiLCLDHuffEnc52, + c_aauiLCLDHuffEnc53, + c_aauiLCLDHuffEnc54, + c_aauiLCLDHuffEnc55, + c_aauiLCLDHuffEnc56, + c_aauiLCLDHuffEnc57, + c_aauiLCLDHuffEnc58, + c_aauiLCLDHuffEnc59, + c_aauiLCLDHuffEnc60, + c_aauiLCLDHuffEnc61, + c_aauiLCLDHuffEnc62, + c_aauiLCLDHuffEnc63, + }; + +const uint32_t num_row_aauiLCLDHuff[2 * ALLOC_TABLE_SIZE] = { 0, 16, 16, 25, 36, 36, 49, 64, 81, 100, + 169, 196, 289, 324, 400, 576, 729, 729, 28, 29, + 32, 37, 39, 46, 55, 65, 77, 91, 109, 129, + 153, 181, 0, 16, 16, 25, 36, 36, 49, 64, 81, + 100, 169, 196, 289, 324, 400, 576, 729, 729, 28, + 29, 32, 37, 39, 46, 55, 65, 77, 91, 109, + 129, 153, 181 }; +#ifdef USE_DEMOD_TABLES +const int32_t c_aaiHuffDemod1[16][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, +}; + +const int32_t c_aaiHuffDemod2[16][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, +}; + +const int32_t c_aaiHuffDemod3[25][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, +}; + +const int32_t c_aaiHuffDemod4[36][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, +}; + +const int32_t c_aaiHuffDemod5[36][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, +}; + +const int32_t c_aaiHuffDemod6[49][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, +}; + +const int32_t c_aaiHuffDemod7[64][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, +}; + +const int32_t c_aaiHuffDemod8[81][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, +}; + +const int32_t c_aaiHuffDemod9[100][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, +}; + +const int32_t c_aaiHuffDemod10[169][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, +}; + +const int32_t c_aaiHuffDemod11[196][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, +}; + +const int32_t c_aaiHuffDemod12[289][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 0, + 14, + 0, + 15, + 0, + 16, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 1, + 14, + 1, + 15, + 1, + 16, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 2, + 14, + 2, + 15, + 2, + 16, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 3, + 14, + 3, + 15, + 3, + 16, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 4, + 14, + 4, + 15, + 4, + 16, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 5, + 14, + 5, + 15, + 5, + 16, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 6, + 14, + 6, + 15, + 6, + 16, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 7, + 14, + 7, + 15, + 7, + 16, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 8, + 14, + 8, + 15, + 8, + 16, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 9, + 14, + 9, + 15, + 9, + 16, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 10, + 14, + 10, + 15, + 10, + 16, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 11, + 14, + 11, + 15, + 11, + 16, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 12, + 14, + 12, + 15, + 12, + 16, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, + 13, + 14, + 13, + 15, + 13, + 16, + 14, + 0, + 14, + 1, + 14, + 2, + 14, + 3, + 14, + 4, + 14, + 5, + 14, + 6, + 14, + 7, + 14, + 8, + 14, + 9, + 14, + 10, + 14, + 11, + 14, + 12, + 14, + 13, + 14, + 14, + 14, + 15, + 14, + 16, + 15, + 0, + 15, + 1, + 15, + 2, + 15, + 3, + 15, + 4, + 15, + 5, + 15, + 6, + 15, + 7, + 15, + 8, + 15, + 9, + 15, + 10, + 15, + 11, + 15, + 12, + 15, + 13, + 15, + 14, + 15, + 15, + 15, + 16, + 16, + 0, + 16, + 1, + 16, + 2, + 16, + 3, + 16, + 4, + 16, + 5, + 16, + 6, + 16, + 7, + 16, + 8, + 16, + 9, + 16, + 10, + 16, + 11, + 16, + 12, + 16, + 13, + 16, + 14, + 16, + 15, + 16, + 16, +}; + +const int32_t c_aaiHuffDemod13[324][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 0, + 14, + 0, + 15, + 0, + 16, + 0, + 17, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 1, + 14, + 1, + 15, + 1, + 16, + 1, + 17, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 2, + 14, + 2, + 15, + 2, + 16, + 2, + 17, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 3, + 14, + 3, + 15, + 3, + 16, + 3, + 17, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 4, + 14, + 4, + 15, + 4, + 16, + 4, + 17, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 5, + 14, + 5, + 15, + 5, + 16, + 5, + 17, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 6, + 14, + 6, + 15, + 6, + 16, + 6, + 17, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 7, + 14, + 7, + 15, + 7, + 16, + 7, + 17, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 8, + 14, + 8, + 15, + 8, + 16, + 8, + 17, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 9, + 14, + 9, + 15, + 9, + 16, + 9, + 17, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 10, + 14, + 10, + 15, + 10, + 16, + 10, + 17, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 11, + 14, + 11, + 15, + 11, + 16, + 11, + 17, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 12, + 14, + 12, + 15, + 12, + 16, + 12, + 17, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, + 13, + 14, + 13, + 15, + 13, + 16, + 13, + 17, + 14, + 0, + 14, + 1, + 14, + 2, + 14, + 3, + 14, + 4, + 14, + 5, + 14, + 6, + 14, + 7, + 14, + 8, + 14, + 9, + 14, + 10, + 14, + 11, + 14, + 12, + 14, + 13, + 14, + 14, + 14, + 15, + 14, + 16, + 14, + 17, + 15, + 0, + 15, + 1, + 15, + 2, + 15, + 3, + 15, + 4, + 15, + 5, + 15, + 6, + 15, + 7, + 15, + 8, + 15, + 9, + 15, + 10, + 15, + 11, + 15, + 12, + 15, + 13, + 15, + 14, + 15, + 15, + 15, + 16, + 15, + 17, + 16, + 0, + 16, + 1, + 16, + 2, + 16, + 3, + 16, + 4, + 16, + 5, + 16, + 6, + 16, + 7, + 16, + 8, + 16, + 9, + 16, + 10, + 16, + 11, + 16, + 12, + 16, + 13, + 16, + 14, + 16, + 15, + 16, + 16, + 16, + 17, + 17, + 0, + 17, + 1, + 17, + 2, + 17, + 3, + 17, + 4, + 17, + 5, + 17, + 6, + 17, + 7, + 17, + 8, + 17, + 9, + 17, + 10, + 17, + 11, + 17, + 12, + 17, + 13, + 17, + 14, + 17, + 15, + 17, + 16, + 17, + 17, +}; + +const int32_t c_aaiHuffDemod14[400][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 0, + 14, + 0, + 15, + 0, + 16, + 0, + 17, + 0, + 18, + 0, + 19, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 1, + 14, + 1, + 15, + 1, + 16, + 1, + 17, + 1, + 18, + 1, + 19, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 2, + 14, + 2, + 15, + 2, + 16, + 2, + 17, + 2, + 18, + 2, + 19, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 3, + 14, + 3, + 15, + 3, + 16, + 3, + 17, + 3, + 18, + 3, + 19, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 4, + 14, + 4, + 15, + 4, + 16, + 4, + 17, + 4, + 18, + 4, + 19, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 5, + 14, + 5, + 15, + 5, + 16, + 5, + 17, + 5, + 18, + 5, + 19, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 6, + 14, + 6, + 15, + 6, + 16, + 6, + 17, + 6, + 18, + 6, + 19, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 7, + 14, + 7, + 15, + 7, + 16, + 7, + 17, + 7, + 18, + 7, + 19, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 8, + 14, + 8, + 15, + 8, + 16, + 8, + 17, + 8, + 18, + 8, + 19, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 9, + 14, + 9, + 15, + 9, + 16, + 9, + 17, + 9, + 18, + 9, + 19, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 10, + 14, + 10, + 15, + 10, + 16, + 10, + 17, + 10, + 18, + 10, + 19, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 11, + 14, + 11, + 15, + 11, + 16, + 11, + 17, + 11, + 18, + 11, + 19, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 12, + 14, + 12, + 15, + 12, + 16, + 12, + 17, + 12, + 18, + 12, + 19, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, + 13, + 14, + 13, + 15, + 13, + 16, + 13, + 17, + 13, + 18, + 13, + 19, + 14, + 0, + 14, + 1, + 14, + 2, + 14, + 3, + 14, + 4, + 14, + 5, + 14, + 6, + 14, + 7, + 14, + 8, + 14, + 9, + 14, + 10, + 14, + 11, + 14, + 12, + 14, + 13, + 14, + 14, + 14, + 15, + 14, + 16, + 14, + 17, + 14, + 18, + 14, + 19, + 15, + 0, + 15, + 1, + 15, + 2, + 15, + 3, + 15, + 4, + 15, + 5, + 15, + 6, + 15, + 7, + 15, + 8, + 15, + 9, + 15, + 10, + 15, + 11, + 15, + 12, + 15, + 13, + 15, + 14, + 15, + 15, + 15, + 16, + 15, + 17, + 15, + 18, + 15, + 19, + 16, + 0, + 16, + 1, + 16, + 2, + 16, + 3, + 16, + 4, + 16, + 5, + 16, + 6, + 16, + 7, + 16, + 8, + 16, + 9, + 16, + 10, + 16, + 11, + 16, + 12, + 16, + 13, + 16, + 14, + 16, + 15, + 16, + 16, + 16, + 17, + 16, + 18, + 16, + 19, + 17, + 0, + 17, + 1, + 17, + 2, + 17, + 3, + 17, + 4, + 17, + 5, + 17, + 6, + 17, + 7, + 17, + 8, + 17, + 9, + 17, + 10, + 17, + 11, + 17, + 12, + 17, + 13, + 17, + 14, + 17, + 15, + 17, + 16, + 17, + 17, + 17, + 18, + 17, + 19, + 18, + 0, + 18, + 1, + 18, + 2, + 18, + 3, + 18, + 4, + 18, + 5, + 18, + 6, + 18, + 7, + 18, + 8, + 18, + 9, + 18, + 10, + 18, + 11, + 18, + 12, + 18, + 13, + 18, + 14, + 18, + 15, + 18, + 16, + 18, + 17, + 18, + 18, + 18, + 19, + 19, + 0, + 19, + 1, + 19, + 2, + 19, + 3, + 19, + 4, + 19, + 5, + 19, + 6, + 19, + 7, + 19, + 8, + 19, + 9, + 19, + 10, + 19, + 11, + 19, + 12, + 19, + 13, + 19, + 14, + 19, + 15, + 19, + 16, + 19, + 17, + 19, + 18, + 19, + 19, +}; + +const int32_t c_aaiHuffDemod15[576][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 0, + 14, + 0, + 15, + 0, + 16, + 0, + 17, + 0, + 18, + 0, + 19, + 0, + 20, + 0, + 21, + 0, + 22, + 0, + 23, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 1, + 14, + 1, + 15, + 1, + 16, + 1, + 17, + 1, + 18, + 1, + 19, + 1, + 20, + 1, + 21, + 1, + 22, + 1, + 23, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 2, + 14, + 2, + 15, + 2, + 16, + 2, + 17, + 2, + 18, + 2, + 19, + 2, + 20, + 2, + 21, + 2, + 22, + 2, + 23, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 3, + 14, + 3, + 15, + 3, + 16, + 3, + 17, + 3, + 18, + 3, + 19, + 3, + 20, + 3, + 21, + 3, + 22, + 3, + 23, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 4, + 14, + 4, + 15, + 4, + 16, + 4, + 17, + 4, + 18, + 4, + 19, + 4, + 20, + 4, + 21, + 4, + 22, + 4, + 23, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 5, + 14, + 5, + 15, + 5, + 16, + 5, + 17, + 5, + 18, + 5, + 19, + 5, + 20, + 5, + 21, + 5, + 22, + 5, + 23, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 6, + 14, + 6, + 15, + 6, + 16, + 6, + 17, + 6, + 18, + 6, + 19, + 6, + 20, + 6, + 21, + 6, + 22, + 6, + 23, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 7, + 14, + 7, + 15, + 7, + 16, + 7, + 17, + 7, + 18, + 7, + 19, + 7, + 20, + 7, + 21, + 7, + 22, + 7, + 23, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 8, + 14, + 8, + 15, + 8, + 16, + 8, + 17, + 8, + 18, + 8, + 19, + 8, + 20, + 8, + 21, + 8, + 22, + 8, + 23, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 9, + 14, + 9, + 15, + 9, + 16, + 9, + 17, + 9, + 18, + 9, + 19, + 9, + 20, + 9, + 21, + 9, + 22, + 9, + 23, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 10, + 14, + 10, + 15, + 10, + 16, + 10, + 17, + 10, + 18, + 10, + 19, + 10, + 20, + 10, + 21, + 10, + 22, + 10, + 23, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 11, + 14, + 11, + 15, + 11, + 16, + 11, + 17, + 11, + 18, + 11, + 19, + 11, + 20, + 11, + 21, + 11, + 22, + 11, + 23, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 12, + 14, + 12, + 15, + 12, + 16, + 12, + 17, + 12, + 18, + 12, + 19, + 12, + 20, + 12, + 21, + 12, + 22, + 12, + 23, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, + 13, + 14, + 13, + 15, + 13, + 16, + 13, + 17, + 13, + 18, + 13, + 19, + 13, + 20, + 13, + 21, + 13, + 22, + 13, + 23, + 14, + 0, + 14, + 1, + 14, + 2, + 14, + 3, + 14, + 4, + 14, + 5, + 14, + 6, + 14, + 7, + 14, + 8, + 14, + 9, + 14, + 10, + 14, + 11, + 14, + 12, + 14, + 13, + 14, + 14, + 14, + 15, + 14, + 16, + 14, + 17, + 14, + 18, + 14, + 19, + 14, + 20, + 14, + 21, + 14, + 22, + 14, + 23, + 15, + 0, + 15, + 1, + 15, + 2, + 15, + 3, + 15, + 4, + 15, + 5, + 15, + 6, + 15, + 7, + 15, + 8, + 15, + 9, + 15, + 10, + 15, + 11, + 15, + 12, + 15, + 13, + 15, + 14, + 15, + 15, + 15, + 16, + 15, + 17, + 15, + 18, + 15, + 19, + 15, + 20, + 15, + 21, + 15, + 22, + 15, + 23, + 16, + 0, + 16, + 1, + 16, + 2, + 16, + 3, + 16, + 4, + 16, + 5, + 16, + 6, + 16, + 7, + 16, + 8, + 16, + 9, + 16, + 10, + 16, + 11, + 16, + 12, + 16, + 13, + 16, + 14, + 16, + 15, + 16, + 16, + 16, + 17, + 16, + 18, + 16, + 19, + 16, + 20, + 16, + 21, + 16, + 22, + 16, + 23, + 17, + 0, + 17, + 1, + 17, + 2, + 17, + 3, + 17, + 4, + 17, + 5, + 17, + 6, + 17, + 7, + 17, + 8, + 17, + 9, + 17, + 10, + 17, + 11, + 17, + 12, + 17, + 13, + 17, + 14, + 17, + 15, + 17, + 16, + 17, + 17, + 17, + 18, + 17, + 19, + 17, + 20, + 17, + 21, + 17, + 22, + 17, + 23, + 18, + 0, + 18, + 1, + 18, + 2, + 18, + 3, + 18, + 4, + 18, + 5, + 18, + 6, + 18, + 7, + 18, + 8, + 18, + 9, + 18, + 10, + 18, + 11, + 18, + 12, + 18, + 13, + 18, + 14, + 18, + 15, + 18, + 16, + 18, + 17, + 18, + 18, + 18, + 19, + 18, + 20, + 18, + 21, + 18, + 22, + 18, + 23, + 19, + 0, + 19, + 1, + 19, + 2, + 19, + 3, + 19, + 4, + 19, + 5, + 19, + 6, + 19, + 7, + 19, + 8, + 19, + 9, + 19, + 10, + 19, + 11, + 19, + 12, + 19, + 13, + 19, + 14, + 19, + 15, + 19, + 16, + 19, + 17, + 19, + 18, + 19, + 19, + 19, + 20, + 19, + 21, + 19, + 22, + 19, + 23, + 20, + 0, + 20, + 1, + 20, + 2, + 20, + 3, + 20, + 4, + 20, + 5, + 20, + 6, + 20, + 7, + 20, + 8, + 20, + 9, + 20, + 10, + 20, + 11, + 20, + 12, + 20, + 13, + 20, + 14, + 20, + 15, + 20, + 16, + 20, + 17, + 20, + 18, + 20, + 19, + 20, + 20, + 20, + 21, + 20, + 22, + 20, + 23, + 21, + 0, + 21, + 1, + 21, + 2, + 21, + 3, + 21, + 4, + 21, + 5, + 21, + 6, + 21, + 7, + 21, + 8, + 21, + 9, + 21, + 10, + 21, + 11, + 21, + 12, + 21, + 13, + 21, + 14, + 21, + 15, + 21, + 16, + 21, + 17, + 21, + 18, + 21, + 19, + 21, + 20, + 21, + 21, + 21, + 22, + 21, + 23, + 22, + 0, + 22, + 1, + 22, + 2, + 22, + 3, + 22, + 4, + 22, + 5, + 22, + 6, + 22, + 7, + 22, + 8, + 22, + 9, + 22, + 10, + 22, + 11, + 22, + 12, + 22, + 13, + 22, + 14, + 22, + 15, + 22, + 16, + 22, + 17, + 22, + 18, + 22, + 19, + 22, + 20, + 22, + 21, + 22, + 22, + 22, + 23, + 23, + 0, + 23, + 1, + 23, + 2, + 23, + 3, + 23, + 4, + 23, + 5, + 23, + 6, + 23, + 7, + 23, + 8, + 23, + 9, + 23, + 10, + 23, + 11, + 23, + 12, + 23, + 13, + 23, + 14, + 23, + 15, + 23, + 16, + 23, + 17, + 23, + 18, + 23, + 19, + 23, + 20, + 23, + 21, + 23, + 22, + 23, + 23, +}; + +const int32_t c_aaiHuffDemod16[729][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 0, + 14, + 0, + 15, + 0, + 16, + 0, + 17, + 0, + 18, + 0, + 19, + 0, + 20, + 0, + 21, + 0, + 22, + 0, + 23, + 0, + 24, + 0, + 25, + 0, + 26, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 1, + 14, + 1, + 15, + 1, + 16, + 1, + 17, + 1, + 18, + 1, + 19, + 1, + 20, + 1, + 21, + 1, + 22, + 1, + 23, + 1, + 24, + 1, + 25, + 1, + 26, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 2, + 14, + 2, + 15, + 2, + 16, + 2, + 17, + 2, + 18, + 2, + 19, + 2, + 20, + 2, + 21, + 2, + 22, + 2, + 23, + 2, + 24, + 2, + 25, + 2, + 26, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 3, + 14, + 3, + 15, + 3, + 16, + 3, + 17, + 3, + 18, + 3, + 19, + 3, + 20, + 3, + 21, + 3, + 22, + 3, + 23, + 3, + 24, + 3, + 25, + 3, + 26, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 4, + 14, + 4, + 15, + 4, + 16, + 4, + 17, + 4, + 18, + 4, + 19, + 4, + 20, + 4, + 21, + 4, + 22, + 4, + 23, + 4, + 24, + 4, + 25, + 4, + 26, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 5, + 14, + 5, + 15, + 5, + 16, + 5, + 17, + 5, + 18, + 5, + 19, + 5, + 20, + 5, + 21, + 5, + 22, + 5, + 23, + 5, + 24, + 5, + 25, + 5, + 26, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 6, + 14, + 6, + 15, + 6, + 16, + 6, + 17, + 6, + 18, + 6, + 19, + 6, + 20, + 6, + 21, + 6, + 22, + 6, + 23, + 6, + 24, + 6, + 25, + 6, + 26, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 7, + 14, + 7, + 15, + 7, + 16, + 7, + 17, + 7, + 18, + 7, + 19, + 7, + 20, + 7, + 21, + 7, + 22, + 7, + 23, + 7, + 24, + 7, + 25, + 7, + 26, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 8, + 14, + 8, + 15, + 8, + 16, + 8, + 17, + 8, + 18, + 8, + 19, + 8, + 20, + 8, + 21, + 8, + 22, + 8, + 23, + 8, + 24, + 8, + 25, + 8, + 26, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 9, + 14, + 9, + 15, + 9, + 16, + 9, + 17, + 9, + 18, + 9, + 19, + 9, + 20, + 9, + 21, + 9, + 22, + 9, + 23, + 9, + 24, + 9, + 25, + 9, + 26, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 10, + 14, + 10, + 15, + 10, + 16, + 10, + 17, + 10, + 18, + 10, + 19, + 10, + 20, + 10, + 21, + 10, + 22, + 10, + 23, + 10, + 24, + 10, + 25, + 10, + 26, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 11, + 14, + 11, + 15, + 11, + 16, + 11, + 17, + 11, + 18, + 11, + 19, + 11, + 20, + 11, + 21, + 11, + 22, + 11, + 23, + 11, + 24, + 11, + 25, + 11, + 26, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 12, + 14, + 12, + 15, + 12, + 16, + 12, + 17, + 12, + 18, + 12, + 19, + 12, + 20, + 12, + 21, + 12, + 22, + 12, + 23, + 12, + 24, + 12, + 25, + 12, + 26, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, + 13, + 14, + 13, + 15, + 13, + 16, + 13, + 17, + 13, + 18, + 13, + 19, + 13, + 20, + 13, + 21, + 13, + 22, + 13, + 23, + 13, + 24, + 13, + 25, + 13, + 26, + 14, + 0, + 14, + 1, + 14, + 2, + 14, + 3, + 14, + 4, + 14, + 5, + 14, + 6, + 14, + 7, + 14, + 8, + 14, + 9, + 14, + 10, + 14, + 11, + 14, + 12, + 14, + 13, + 14, + 14, + 14, + 15, + 14, + 16, + 14, + 17, + 14, + 18, + 14, + 19, + 14, + 20, + 14, + 21, + 14, + 22, + 14, + 23, + 14, + 24, + 14, + 25, + 14, + 26, + 15, + 0, + 15, + 1, + 15, + 2, + 15, + 3, + 15, + 4, + 15, + 5, + 15, + 6, + 15, + 7, + 15, + 8, + 15, + 9, + 15, + 10, + 15, + 11, + 15, + 12, + 15, + 13, + 15, + 14, + 15, + 15, + 15, + 16, + 15, + 17, + 15, + 18, + 15, + 19, + 15, + 20, + 15, + 21, + 15, + 22, + 15, + 23, + 15, + 24, + 15, + 25, + 15, + 26, + 16, + 0, + 16, + 1, + 16, + 2, + 16, + 3, + 16, + 4, + 16, + 5, + 16, + 6, + 16, + 7, + 16, + 8, + 16, + 9, + 16, + 10, + 16, + 11, + 16, + 12, + 16, + 13, + 16, + 14, + 16, + 15, + 16, + 16, + 16, + 17, + 16, + 18, + 16, + 19, + 16, + 20, + 16, + 21, + 16, + 22, + 16, + 23, + 16, + 24, + 16, + 25, + 16, + 26, + 17, + 0, + 17, + 1, + 17, + 2, + 17, + 3, + 17, + 4, + 17, + 5, + 17, + 6, + 17, + 7, + 17, + 8, + 17, + 9, + 17, + 10, + 17, + 11, + 17, + 12, + 17, + 13, + 17, + 14, + 17, + 15, + 17, + 16, + 17, + 17, + 17, + 18, + 17, + 19, + 17, + 20, + 17, + 21, + 17, + 22, + 17, + 23, + 17, + 24, + 17, + 25, + 17, + 26, + 18, + 0, + 18, + 1, + 18, + 2, + 18, + 3, + 18, + 4, + 18, + 5, + 18, + 6, + 18, + 7, + 18, + 8, + 18, + 9, + 18, + 10, + 18, + 11, + 18, + 12, + 18, + 13, + 18, + 14, + 18, + 15, + 18, + 16, + 18, + 17, + 18, + 18, + 18, + 19, + 18, + 20, + 18, + 21, + 18, + 22, + 18, + 23, + 18, + 24, + 18, + 25, + 18, + 26, + 19, + 0, + 19, + 1, + 19, + 2, + 19, + 3, + 19, + 4, + 19, + 5, + 19, + 6, + 19, + 7, + 19, + 8, + 19, + 9, + 19, + 10, + 19, + 11, + 19, + 12, + 19, + 13, + 19, + 14, + 19, + 15, + 19, + 16, + 19, + 17, + 19, + 18, + 19, + 19, + 19, + 20, + 19, + 21, + 19, + 22, + 19, + 23, + 19, + 24, + 19, + 25, + 19, + 26, + 20, + 0, + 20, + 1, + 20, + 2, + 20, + 3, + 20, + 4, + 20, + 5, + 20, + 6, + 20, + 7, + 20, + 8, + 20, + 9, + 20, + 10, + 20, + 11, + 20, + 12, + 20, + 13, + 20, + 14, + 20, + 15, + 20, + 16, + 20, + 17, + 20, + 18, + 20, + 19, + 20, + 20, + 20, + 21, + 20, + 22, + 20, + 23, + 20, + 24, + 20, + 25, + 20, + 26, + 21, + 0, + 21, + 1, + 21, + 2, + 21, + 3, + 21, + 4, + 21, + 5, + 21, + 6, + 21, + 7, + 21, + 8, + 21, + 9, + 21, + 10, + 21, + 11, + 21, + 12, + 21, + 13, + 21, + 14, + 21, + 15, + 21, + 16, + 21, + 17, + 21, + 18, + 21, + 19, + 21, + 20, + 21, + 21, + 21, + 22, + 21, + 23, + 21, + 24, + 21, + 25, + 21, + 26, + 22, + 0, + 22, + 1, + 22, + 2, + 22, + 3, + 22, + 4, + 22, + 5, + 22, + 6, + 22, + 7, + 22, + 8, + 22, + 9, + 22, + 10, + 22, + 11, + 22, + 12, + 22, + 13, + 22, + 14, + 22, + 15, + 22, + 16, + 22, + 17, + 22, + 18, + 22, + 19, + 22, + 20, + 22, + 21, + 22, + 22, + 22, + 23, + 22, + 24, + 22, + 25, + 22, + 26, + 23, + 0, + 23, + 1, + 23, + 2, + 23, + 3, + 23, + 4, + 23, + 5, + 23, + 6, + 23, + 7, + 23, + 8, + 23, + 9, + 23, + 10, + 23, + 11, + 23, + 12, + 23, + 13, + 23, + 14, + 23, + 15, + 23, + 16, + 23, + 17, + 23, + 18, + 23, + 19, + 23, + 20, + 23, + 21, + 23, + 22, + 23, + 23, + 23, + 24, + 23, + 25, + 23, + 26, + 24, + 0, + 24, + 1, + 24, + 2, + 24, + 3, + 24, + 4, + 24, + 5, + 24, + 6, + 24, + 7, + 24, + 8, + 24, + 9, + 24, + 10, + 24, + 11, + 24, + 12, + 24, + 13, + 24, + 14, + 24, + 15, + 24, + 16, + 24, + 17, + 24, + 18, + 24, + 19, + 24, + 20, + 24, + 21, + 24, + 22, + 24, + 23, + 24, + 24, + 24, + 25, + 24, + 26, + 25, + 0, + 25, + 1, + 25, + 2, + 25, + 3, + 25, + 4, + 25, + 5, + 25, + 6, + 25, + 7, + 25, + 8, + 25, + 9, + 25, + 10, + 25, + 11, + 25, + 12, + 25, + 13, + 25, + 14, + 25, + 15, + 25, + 16, + 25, + 17, + 25, + 18, + 25, + 19, + 25, + 20, + 25, + 21, + 25, + 22, + 25, + 23, + 25, + 24, + 25, + 25, + 25, + 26, + 26, + 0, + 26, + 1, + 26, + 2, + 26, + 3, + 26, + 4, + 26, + 5, + 26, + 6, + 26, + 7, + 26, + 8, + 26, + 9, + 26, + 10, + 26, + 11, + 26, + 12, + 26, + 13, + 26, + 14, + 26, + 15, + 26, + 16, + 26, + 17, + 26, + 18, + 26, + 19, + 26, + 20, + 26, + 21, + 26, + 22, + 26, + 23, + 26, + 24, + 26, + 25, + 26, + 26, +}; + +const int32_t c_aaiHuffDemod17[729][2] = { + 0, + 0, + 0, + 1, + 0, + 2, + 0, + 3, + 0, + 4, + 0, + 5, + 0, + 6, + 0, + 7, + 0, + 8, + 0, + 9, + 0, + 10, + 0, + 11, + 0, + 12, + 0, + 13, + 0, + 14, + 0, + 15, + 0, + 16, + 0, + 17, + 0, + 18, + 0, + 19, + 0, + 20, + 0, + 21, + 0, + 22, + 0, + 23, + 0, + 24, + 0, + 25, + 0, + 26, + 1, + 0, + 1, + 1, + 1, + 2, + 1, + 3, + 1, + 4, + 1, + 5, + 1, + 6, + 1, + 7, + 1, + 8, + 1, + 9, + 1, + 10, + 1, + 11, + 1, + 12, + 1, + 13, + 1, + 14, + 1, + 15, + 1, + 16, + 1, + 17, + 1, + 18, + 1, + 19, + 1, + 20, + 1, + 21, + 1, + 22, + 1, + 23, + 1, + 24, + 1, + 25, + 1, + 26, + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 2, + 5, + 2, + 6, + 2, + 7, + 2, + 8, + 2, + 9, + 2, + 10, + 2, + 11, + 2, + 12, + 2, + 13, + 2, + 14, + 2, + 15, + 2, + 16, + 2, + 17, + 2, + 18, + 2, + 19, + 2, + 20, + 2, + 21, + 2, + 22, + 2, + 23, + 2, + 24, + 2, + 25, + 2, + 26, + 3, + 0, + 3, + 1, + 3, + 2, + 3, + 3, + 3, + 4, + 3, + 5, + 3, + 6, + 3, + 7, + 3, + 8, + 3, + 9, + 3, + 10, + 3, + 11, + 3, + 12, + 3, + 13, + 3, + 14, + 3, + 15, + 3, + 16, + 3, + 17, + 3, + 18, + 3, + 19, + 3, + 20, + 3, + 21, + 3, + 22, + 3, + 23, + 3, + 24, + 3, + 25, + 3, + 26, + 4, + 0, + 4, + 1, + 4, + 2, + 4, + 3, + 4, + 4, + 4, + 5, + 4, + 6, + 4, + 7, + 4, + 8, + 4, + 9, + 4, + 10, + 4, + 11, + 4, + 12, + 4, + 13, + 4, + 14, + 4, + 15, + 4, + 16, + 4, + 17, + 4, + 18, + 4, + 19, + 4, + 20, + 4, + 21, + 4, + 22, + 4, + 23, + 4, + 24, + 4, + 25, + 4, + 26, + 5, + 0, + 5, + 1, + 5, + 2, + 5, + 3, + 5, + 4, + 5, + 5, + 5, + 6, + 5, + 7, + 5, + 8, + 5, + 9, + 5, + 10, + 5, + 11, + 5, + 12, + 5, + 13, + 5, + 14, + 5, + 15, + 5, + 16, + 5, + 17, + 5, + 18, + 5, + 19, + 5, + 20, + 5, + 21, + 5, + 22, + 5, + 23, + 5, + 24, + 5, + 25, + 5, + 26, + 6, + 0, + 6, + 1, + 6, + 2, + 6, + 3, + 6, + 4, + 6, + 5, + 6, + 6, + 6, + 7, + 6, + 8, + 6, + 9, + 6, + 10, + 6, + 11, + 6, + 12, + 6, + 13, + 6, + 14, + 6, + 15, + 6, + 16, + 6, + 17, + 6, + 18, + 6, + 19, + 6, + 20, + 6, + 21, + 6, + 22, + 6, + 23, + 6, + 24, + 6, + 25, + 6, + 26, + 7, + 0, + 7, + 1, + 7, + 2, + 7, + 3, + 7, + 4, + 7, + 5, + 7, + 6, + 7, + 7, + 7, + 8, + 7, + 9, + 7, + 10, + 7, + 11, + 7, + 12, + 7, + 13, + 7, + 14, + 7, + 15, + 7, + 16, + 7, + 17, + 7, + 18, + 7, + 19, + 7, + 20, + 7, + 21, + 7, + 22, + 7, + 23, + 7, + 24, + 7, + 25, + 7, + 26, + 8, + 0, + 8, + 1, + 8, + 2, + 8, + 3, + 8, + 4, + 8, + 5, + 8, + 6, + 8, + 7, + 8, + 8, + 8, + 9, + 8, + 10, + 8, + 11, + 8, + 12, + 8, + 13, + 8, + 14, + 8, + 15, + 8, + 16, + 8, + 17, + 8, + 18, + 8, + 19, + 8, + 20, + 8, + 21, + 8, + 22, + 8, + 23, + 8, + 24, + 8, + 25, + 8, + 26, + 9, + 0, + 9, + 1, + 9, + 2, + 9, + 3, + 9, + 4, + 9, + 5, + 9, + 6, + 9, + 7, + 9, + 8, + 9, + 9, + 9, + 10, + 9, + 11, + 9, + 12, + 9, + 13, + 9, + 14, + 9, + 15, + 9, + 16, + 9, + 17, + 9, + 18, + 9, + 19, + 9, + 20, + 9, + 21, + 9, + 22, + 9, + 23, + 9, + 24, + 9, + 25, + 9, + 26, + 10, + 0, + 10, + 1, + 10, + 2, + 10, + 3, + 10, + 4, + 10, + 5, + 10, + 6, + 10, + 7, + 10, + 8, + 10, + 9, + 10, + 10, + 10, + 11, + 10, + 12, + 10, + 13, + 10, + 14, + 10, + 15, + 10, + 16, + 10, + 17, + 10, + 18, + 10, + 19, + 10, + 20, + 10, + 21, + 10, + 22, + 10, + 23, + 10, + 24, + 10, + 25, + 10, + 26, + 11, + 0, + 11, + 1, + 11, + 2, + 11, + 3, + 11, + 4, + 11, + 5, + 11, + 6, + 11, + 7, + 11, + 8, + 11, + 9, + 11, + 10, + 11, + 11, + 11, + 12, + 11, + 13, + 11, + 14, + 11, + 15, + 11, + 16, + 11, + 17, + 11, + 18, + 11, + 19, + 11, + 20, + 11, + 21, + 11, + 22, + 11, + 23, + 11, + 24, + 11, + 25, + 11, + 26, + 12, + 0, + 12, + 1, + 12, + 2, + 12, + 3, + 12, + 4, + 12, + 5, + 12, + 6, + 12, + 7, + 12, + 8, + 12, + 9, + 12, + 10, + 12, + 11, + 12, + 12, + 12, + 13, + 12, + 14, + 12, + 15, + 12, + 16, + 12, + 17, + 12, + 18, + 12, + 19, + 12, + 20, + 12, + 21, + 12, + 22, + 12, + 23, + 12, + 24, + 12, + 25, + 12, + 26, + 13, + 0, + 13, + 1, + 13, + 2, + 13, + 3, + 13, + 4, + 13, + 5, + 13, + 6, + 13, + 7, + 13, + 8, + 13, + 9, + 13, + 10, + 13, + 11, + 13, + 12, + 13, + 13, + 13, + 14, + 13, + 15, + 13, + 16, + 13, + 17, + 13, + 18, + 13, + 19, + 13, + 20, + 13, + 21, + 13, + 22, + 13, + 23, + 13, + 24, + 13, + 25, + 13, + 26, + 14, + 0, + 14, + 1, + 14, + 2, + 14, + 3, + 14, + 4, + 14, + 5, + 14, + 6, + 14, + 7, + 14, + 8, + 14, + 9, + 14, + 10, + 14, + 11, + 14, + 12, + 14, + 13, + 14, + 14, + 14, + 15, + 14, + 16, + 14, + 17, + 14, + 18, + 14, + 19, + 14, + 20, + 14, + 21, + 14, + 22, + 14, + 23, + 14, + 24, + 14, + 25, + 14, + 26, + 15, + 0, + 15, + 1, + 15, + 2, + 15, + 3, + 15, + 4, + 15, + 5, + 15, + 6, + 15, + 7, + 15, + 8, + 15, + 9, + 15, + 10, + 15, + 11, + 15, + 12, + 15, + 13, + 15, + 14, + 15, + 15, + 15, + 16, + 15, + 17, + 15, + 18, + 15, + 19, + 15, + 20, + 15, + 21, + 15, + 22, + 15, + 23, + 15, + 24, + 15, + 25, + 15, + 26, + 16, + 0, + 16, + 1, + 16, + 2, + 16, + 3, + 16, + 4, + 16, + 5, + 16, + 6, + 16, + 7, + 16, + 8, + 16, + 9, + 16, + 10, + 16, + 11, + 16, + 12, + 16, + 13, + 16, + 14, + 16, + 15, + 16, + 16, + 16, + 17, + 16, + 18, + 16, + 19, + 16, + 20, + 16, + 21, + 16, + 22, + 16, + 23, + 16, + 24, + 16, + 25, + 16, + 26, + 17, + 0, + 17, + 1, + 17, + 2, + 17, + 3, + 17, + 4, + 17, + 5, + 17, + 6, + 17, + 7, + 17, + 8, + 17, + 9, + 17, + 10, + 17, + 11, + 17, + 12, + 17, + 13, + 17, + 14, + 17, + 15, + 17, + 16, + 17, + 17, + 17, + 18, + 17, + 19, + 17, + 20, + 17, + 21, + 17, + 22, + 17, + 23, + 17, + 24, + 17, + 25, + 17, + 26, + 18, + 0, + 18, + 1, + 18, + 2, + 18, + 3, + 18, + 4, + 18, + 5, + 18, + 6, + 18, + 7, + 18, + 8, + 18, + 9, + 18, + 10, + 18, + 11, + 18, + 12, + 18, + 13, + 18, + 14, + 18, + 15, + 18, + 16, + 18, + 17, + 18, + 18, + 18, + 19, + 18, + 20, + 18, + 21, + 18, + 22, + 18, + 23, + 18, + 24, + 18, + 25, + 18, + 26, + 19, + 0, + 19, + 1, + 19, + 2, + 19, + 3, + 19, + 4, + 19, + 5, + 19, + 6, + 19, + 7, + 19, + 8, + 19, + 9, + 19, + 10, + 19, + 11, + 19, + 12, + 19, + 13, + 19, + 14, + 19, + 15, + 19, + 16, + 19, + 17, + 19, + 18, + 19, + 19, + 19, + 20, + 19, + 21, + 19, + 22, + 19, + 23, + 19, + 24, + 19, + 25, + 19, + 26, + 20, + 0, + 20, + 1, + 20, + 2, + 20, + 3, + 20, + 4, + 20, + 5, + 20, + 6, + 20, + 7, + 20, + 8, + 20, + 9, + 20, + 10, + 20, + 11, + 20, + 12, + 20, + 13, + 20, + 14, + 20, + 15, + 20, + 16, + 20, + 17, + 20, + 18, + 20, + 19, + 20, + 20, + 20, + 21, + 20, + 22, + 20, + 23, + 20, + 24, + 20, + 25, + 20, + 26, + 21, + 0, + 21, + 1, + 21, + 2, + 21, + 3, + 21, + 4, + 21, + 5, + 21, + 6, + 21, + 7, + 21, + 8, + 21, + 9, + 21, + 10, + 21, + 11, + 21, + 12, + 21, + 13, + 21, + 14, + 21, + 15, + 21, + 16, + 21, + 17, + 21, + 18, + 21, + 19, + 21, + 20, + 21, + 21, + 21, + 22, + 21, + 23, + 21, + 24, + 21, + 25, + 21, + 26, + 22, + 0, + 22, + 1, + 22, + 2, + 22, + 3, + 22, + 4, + 22, + 5, + 22, + 6, + 22, + 7, + 22, + 8, + 22, + 9, + 22, + 10, + 22, + 11, + 22, + 12, + 22, + 13, + 22, + 14, + 22, + 15, + 22, + 16, + 22, + 17, + 22, + 18, + 22, + 19, + 22, + 20, + 22, + 21, + 22, + 22, + 22, + 23, + 22, + 24, + 22, + 25, + 22, + 26, + 23, + 0, + 23, + 1, + 23, + 2, + 23, + 3, + 23, + 4, + 23, + 5, + 23, + 6, + 23, + 7, + 23, + 8, + 23, + 9, + 23, + 10, + 23, + 11, + 23, + 12, + 23, + 13, + 23, + 14, + 23, + 15, + 23, + 16, + 23, + 17, + 23, + 18, + 23, + 19, + 23, + 20, + 23, + 21, + 23, + 22, + 23, + 23, + 23, + 24, + 23, + 25, + 23, + 26, + 24, + 0, + 24, + 1, + 24, + 2, + 24, + 3, + 24, + 4, + 24, + 5, + 24, + 6, + 24, + 7, + 24, + 8, + 24, + 9, + 24, + 10, + 24, + 11, + 24, + 12, + 24, + 13, + 24, + 14, + 24, + 15, + 24, + 16, + 24, + 17, + 24, + 18, + 24, + 19, + 24, + 20, + 24, + 21, + 24, + 22, + 24, + 23, + 24, + 24, + 24, + 25, + 24, + 26, + 25, + 0, + 25, + 1, + 25, + 2, + 25, + 3, + 25, + 4, + 25, + 5, + 25, + 6, + 25, + 7, + 25, + 8, + 25, + 9, + 25, + 10, + 25, + 11, + 25, + 12, + 25, + 13, + 25, + 14, + 25, + 15, + 25, + 16, + 25, + 17, + 25, + 18, + 25, + 19, + 25, + 20, + 25, + 21, + 25, + 22, + 25, + 23, + 25, + 24, + 25, + 25, + 25, + 26, + 26, + 0, + 26, + 1, + 26, + 2, + 26, + 3, + 26, + 4, + 26, + 5, + 26, + 6, + 26, + 7, + 26, + 8, + 26, + 9, + 26, + 10, + 26, + 11, + 26, + 12, + 26, + 13, + 26, + 14, + 26, + 15, + 26, + 16, + 26, + 17, + 26, + 18, + 26, + 19, + 26, + 20, + 26, + 21, + 26, + 22, + 26, + 23, + 26, + 24, + 26, + 25, + 26, + 26, +}; + +const int32_t ( *c_apaiDemodTables[ALLOC_TABLE_SIZE] )[2] = { + NULL, + c_aaiHuffDemod1, + c_aaiHuffDemod2, + c_aaiHuffDemod3, + c_aaiHuffDemod4, + c_aaiHuffDemod5, + c_aaiHuffDemod6, + c_aaiHuffDemod7, + c_aaiHuffDemod8, + c_aaiHuffDemod9, + c_aaiHuffDemod10, + c_aaiHuffDemod11, + c_aaiHuffDemod12, + c_aaiHuffDemod13, + c_aaiHuffDemod14, + c_aaiHuffDemod15, + c_aaiHuffDemod16, + c_aaiHuffDemod17, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; +#endif +const Word16 c_aiLogAddTable_fx[LOG_ADD_TABLE_LENGTH] = { + 0x40, + 0x40, + 0x3F, + 0x3F, + 0x3E, + 0x3E, + 0x3D, + 0x3D, + 0x3C, + 0x3C, + 0x3B, + 0x3B, + 0x3A, + 0x3A, + 0x39, + 0x39, + 0x38, + 0x38, + 0x37, + 0x37, + 0x37, + 0x36, + 0x36, + 0x35, + 0x35, + 0x34, + 0x34, + 0x33, + 0x33, + 0x33, + 0x32, + 0x32, + 0x31, + 0x31, + 0x31, + 0x30, + 0x30, + 0x2F, + 0x2F, + 0x2F, + 0x2E, + 0x2E, + 0x2D, + 0x2D, + 0x2D, + 0x2C, + 0x2C, + 0x2B, + 0x2B, + 0x2B, + 0x2A, + 0x2A, + 0x2A, + 0x29, + 0x29, + 0x29, + 0x28, + 0x28, + 0x27, + 0x27, + 0x27, + 0x26, + 0x26, + 0x26, + 0x25, + 0x25, + 0x25, + 0x24, + 0x24, + 0x24, + 0x23, + 0x23, + 0x23, + 0x23, + 0x22, + 0x22, + 0x22, + 0x21, + 0x21, + 0x21, + 0x20, + 0x20, + 0x20, + 0x20, + 0x1F, + 0x1F, + 0x1F, + 0x1E, + 0x1E, + 0x1E, + 0x1E, + 0x1D, + 0x1D, + 0x1D, + 0x1C, + 0x1C, + 0x1C, + 0x1C, + 0x1B, + 0x1B, + 0x1B, + 0x1B, + 0x1A, + 0x1A, + 0x1A, + 0x1A, + 0x19, + 0x19, + 0x19, + 0x19, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x17, + 0x17, + 0x17, + 0x17, + 0x16, + 0x16, + 0x16, + 0x16, + 0x16, + 0x15, + 0x15, + 0x15, + 0x15, + 0x15, + 0x14, + 0x14, + 0x14, + 0x14, + 0x14, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x12, + 0x12, + 0x12, + 0x12, + 0x12, + 0x11, + 0x11, + 0x11, + 0x11, + 0x11, + 0x11, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 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, + 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, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; +const int32_t c_aiLogAddTable[LOG_ADD_TABLE_LENGTH] = { + 0x40, + 0x40, + 0x3F, + 0x3F, + 0x3E, + 0x3E, + 0x3D, + 0x3D, + 0x3C, + 0x3C, + 0x3B, + 0x3B, + 0x3A, + 0x3A, + 0x39, + 0x39, + 0x38, + 0x38, + 0x37, + 0x37, + 0x37, + 0x36, + 0x36, + 0x35, + 0x35, + 0x34, + 0x34, + 0x33, + 0x33, + 0x33, + 0x32, + 0x32, + 0x31, + 0x31, + 0x31, + 0x30, + 0x30, + 0x2F, + 0x2F, + 0x2F, + 0x2E, + 0x2E, + 0x2D, + 0x2D, + 0x2D, + 0x2C, + 0x2C, + 0x2B, + 0x2B, + 0x2B, + 0x2A, + 0x2A, + 0x2A, + 0x29, + 0x29, + 0x29, + 0x28, + 0x28, + 0x27, + 0x27, + 0x27, + 0x26, + 0x26, + 0x26, + 0x25, + 0x25, + 0x25, + 0x24, + 0x24, + 0x24, + 0x23, + 0x23, + 0x23, + 0x23, + 0x22, + 0x22, + 0x22, + 0x21, + 0x21, + 0x21, + 0x20, + 0x20, + 0x20, + 0x20, + 0x1F, + 0x1F, + 0x1F, + 0x1E, + 0x1E, + 0x1E, + 0x1E, + 0x1D, + 0x1D, + 0x1D, + 0x1C, + 0x1C, + 0x1C, + 0x1C, + 0x1B, + 0x1B, + 0x1B, + 0x1B, + 0x1A, + 0x1A, + 0x1A, + 0x1A, + 0x19, + 0x19, + 0x19, + 0x19, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x17, + 0x17, + 0x17, + 0x17, + 0x16, + 0x16, + 0x16, + 0x16, + 0x16, + 0x15, + 0x15, + 0x15, + 0x15, + 0x15, + 0x14, + 0x14, + 0x14, + 0x14, + 0x14, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x12, + 0x12, + 0x12, + 0x12, + 0x12, + 0x11, + 0x11, + 0x11, + 0x11, + 0x11, + 0x11, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x10, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0F, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0D, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0B, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x0A, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x09, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x08, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x07, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x06, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x05, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x04, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 0x02, + 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, + 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, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +}; +const Word16 c_aiBandwidthAdjust48_fx[MAX_BANDS_48] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 64, + 64, + 64, + 64, + 101, + 101, + 128, + 165, + 165, + 180, + 213, +}; +const int32_t c_aiBandwidthAdjust48[MAX_BANDS_48] = { + + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 64, + 64, + 64, + 64, + 101, + 101, + 128, + 165, + 165, + 180, + 213, +}; + +const Word16 c_aiAbsoluteThresh48_fx[MAX_BANDS_48] = { + -1787, + -1787, + -1787, + -1787, + -1787, + -1787, + -1787, + -1787, + -1782, + -1761, + -1737, + -1679, + -1638, + -1613, + -1590, + -1568, + -1516, + -1459, + -1395, + -1289, + -671, + -409, + -401, +}; +const int32_t c_aiAbsoluteThresh48[MAX_BANDS_48] = { + -1787, + -1787, + -1787, + -1787, + -1787, + -1787, + -1787, + -1787, + -1782, + -1761, + -1737, + -1679, + -1638, + -1613, + -1590, + -1568, + -1516, + -1459, + -1395, + -1289, + -671, + -409, + -401, +}; +#if PERCEPTUAL_MODEL_SLGAIN_SHIFT == 4 +const int32_t c_aiDefaultTheta48[MAX_BANDS_48] = { + 7, + 7, + 6, + 5, + 5, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, + 4, +}; +#elif PERCEPTUAL_MODEL_SLGAIN_SHIFT == 8 +const Word16 c_aiDefaultTheta48_fx[MAX_BANDS_48] = { + + 112, + 112, + 96, + 80, + 80, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, +}; +#endif +const int32_t c_aiDefaultTheta48[MAX_BANDS_48] = { + + 112, + 112, + 96, + 80, + 80, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, + 64, +}; +const Word16 c_aaiSpreadFunction48_fx[MAX_BANDS_48 * MAX_BANDS_48] = { + 0, + -1561, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -289, + -4, + -1234, + -2295, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -569, + -229, + -8, + -905, + -1705, + -2324, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -789, + -445, + -173, + -16, + -656, + -1271, + -1765, + -2172, + -2520, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -961, + -616, + -340, + -136, + -28, + -488, + -976, + -1382, + -1729, + -2032, + -2305, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1088, + -743, + -465, + -257, + -148, + -31, + -371, + -769, + -1114, + -1417, + -1689, + -2054, + -2483, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1198, + -852, + -574, + -364, + -209, + -148, + -42, + -300, + -635, + -936, + -1207, + -1572, + -2000, + -2376, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1293, + -948, + -669, + -458, + -301, + -183, + -145, + -56, + -258, + -547, + -816, + -1179, + -1606, + -1982, + -2311, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1375, + -1029, + -750, + -539, + -381, + -260, + -180, + -142, + -68, + -231, + -487, + -846, + -1272, + -1647, + -1976, + -2261, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1444, + -1099, + -820, + -608, + -449, + -328, + -233, + -194, + -138, + -77, + -213, + -555, + -978, + -1352, + -1681, + -1966, + -2268, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1501, + -1155, + -876, + -665, + -505, + -383, + -287, + -210, + -193, + -130, + -79, + -298, + -711, + -1083, + -1411, + -1696, + -1997, + -2288, + -2550, + -2552, + -2552, + -2552, + -2552, + -1567, + -1221, + -942, + -730, + -570, + -448, + -351, + -272, + -206, + -189, + -151, + -72, + -349, + -713, + -1039, + -1324, + -1625, + -1915, + -2177, + -2448, + -2552, + -2552, + -2552, + -1650, + -1304, + -1025, + -813, + -653, + -530, + -432, + -352, + -285, + -227, + -177, + -163, + -69, + -297, + -613, + -895, + -1195, + -1485, + -1746, + -2017, + -2238, + -2401, + -2545, + -1727, + -1381, + -1102, + -890, + -730, + -607, + -509, + -428, + -360, + -301, + -249, + -180, + -153, + -72, + -257, + -527, + -824, + -1112, + -1373, + -1643, + -1865, + -2028, + -2171, + -1798, + -1452, + -1173, + -960, + -800, + -677, + -579, + -498, + -430, + -370, + -317, + -246, + -192, + -145, + -76, + -224, + -505, + -790, + -1050, + -1320, + -1540, + -1703, + -1847, + -1860, + -1514, + -1234, + -1022, + -862, + -738, + -640, + -559, + -490, + -430, + -377, + -306, + -224, + -197, + -136, + -81, + -242, + -515, + -771, + -1040, + -1260, + -1422, + -1566, + -1923, + -1577, + -1297, + -1085, + -925, + -801, + -703, + -621, + -553, + -492, + -439, + -367, + -284, + -213, + -198, + -144, + -83, + -235, + -479, + -744, + -963, + -1125, + -1268, + -1986, + -1640, + -1360, + -1148, + -988, + -864, + -766, + -684, + -615, + -555, + -501, + -429, + -345, + -273, + -211, + -204, + -146, + -89, + -216, + -465, + -680, + -841, + -984, + -2043, + -1697, + -1417, + -1205, + -1044, + -921, + -822, + -741, + -672, + -611, + -557, + -485, + -401, + -328, + -264, + -211, + -205, + -140, + -93, + -227, + -430, + -588, + -729, + -2104, + -1758, + -1479, + -1266, + -1106, + -982, + -884, + -802, + -733, + -673, + -619, + -546, + -461, + -388, + -324, + -269, + -212, + -211, + -151, + -100, + -195, + -336, + -472, + -2163, + -1817, + -1537, + -1324, + -1164, + -1040, + -942, + -860, + -791, + -731, + -676, + -604, + -519, + -445, + -380, + -325, + -268, + -226, + -219, + -147, + -114, + -167, + -280, + -2203, + -1857, + -1577, + -1365, + -1205, + -1081, + -982, + -901, + -831, + -771, + -717, + -644, + -559, + -485, + -420, + -364, + -306, + -252, + -239, + -206, + -132, + -122, + -163, + -2224, + -1878, + -1598, + -1386, + -1225, + -1102, + -1003, + -921, + -852, + -792, + -737, + -665, + -580, + -505, + -441, + -385, + -326, + -271, + -222, + -224, + -176, + -121, + -114, +}; +const int32_t c_aaiSpreadFunction48[MAX_BANDS_48 * MAX_BANDS_48] = { + 0, + -1561, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -289, + -4, + -1234, + -2295, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -569, + -229, + -8, + -905, + -1705, + -2324, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -789, + -445, + -173, + -16, + -656, + -1271, + -1765, + -2172, + -2520, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -961, + -616, + -340, + -136, + -28, + -488, + -976, + -1382, + -1729, + -2032, + -2305, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1088, + -743, + -465, + -257, + -148, + -31, + -371, + -769, + -1114, + -1417, + -1689, + -2054, + -2483, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1198, + -852, + -574, + -364, + -209, + -148, + -42, + -300, + -635, + -936, + -1207, + -1572, + -2000, + -2376, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1293, + -948, + -669, + -458, + -301, + -183, + -145, + -56, + -258, + -547, + -816, + -1179, + -1606, + -1982, + -2311, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1375, + -1029, + -750, + -539, + -381, + -260, + -180, + -142, + -68, + -231, + -487, + -846, + -1272, + -1647, + -1976, + -2261, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1444, + -1099, + -820, + -608, + -449, + -328, + -233, + -194, + -138, + -77, + -213, + -555, + -978, + -1352, + -1681, + -1966, + -2268, + -2552, + -2552, + -2552, + -2552, + -2552, + -2552, + -1501, + -1155, + -876, + -665, + -505, + -383, + -287, + -210, + -193, + -130, + -79, + -298, + -711, + -1083, + -1411, + -1696, + -1997, + -2288, + -2550, + -2552, + -2552, + -2552, + -2552, + -1567, + -1221, + -942, + -730, + -570, + -448, + -351, + -272, + -206, + -189, + -151, + -72, + -349, + -713, + -1039, + -1324, + -1625, + -1915, + -2177, + -2448, + -2552, + -2552, + -2552, + -1650, + -1304, + -1025, + -813, + -653, + -530, + -432, + -352, + -285, + -227, + -177, + -163, + -69, + -297, + -613, + -895, + -1195, + -1485, + -1746, + -2017, + -2238, + -2401, + -2545, + -1727, + -1381, + -1102, + -890, + -730, + -607, + -509, + -428, + -360, + -301, + -249, + -180, + -153, + -72, + -257, + -527, + -824, + -1112, + -1373, + -1643, + -1865, + -2028, + -2171, + -1798, + -1452, + -1173, + -960, + -800, + -677, + -579, + -498, + -430, + -370, + -317, + -246, + -192, + -145, + -76, + -224, + -505, + -790, + -1050, + -1320, + -1540, + -1703, + -1847, + -1860, + -1514, + -1234, + -1022, + -862, + -738, + -640, + -559, + -490, + -430, + -377, + -306, + -224, + -197, + -136, + -81, + -242, + -515, + -771, + -1040, + -1260, + -1422, + -1566, + -1923, + -1577, + -1297, + -1085, + -925, + -801, + -703, + -621, + -553, + -492, + -439, + -367, + -284, + -213, + -198, + -144, + -83, + -235, + -479, + -744, + -963, + -1125, + -1268, + -1986, + -1640, + -1360, + -1148, + -988, + -864, + -766, + -684, + -615, + -555, + -501, + -429, + -345, + -273, + -211, + -204, + -146, + -89, + -216, + -465, + -680, + -841, + -984, + -2043, + -1697, + -1417, + -1205, + -1044, + -921, + -822, + -741, + -672, + -611, + -557, + -485, + -401, + -328, + -264, + -211, + -205, + -140, + -93, + -227, + -430, + -588, + -729, + -2104, + -1758, + -1479, + -1266, + -1106, + -982, + -884, + -802, + -733, + -673, + -619, + -546, + -461, + -388, + -324, + -269, + -212, + -211, + -151, + -100, + -195, + -336, + -472, + -2163, + -1817, + -1537, + -1324, + -1164, + -1040, + -942, + -860, + -791, + -731, + -676, + -604, + -519, + -445, + -380, + -325, + -268, + -226, + -219, + -147, + -114, + -167, + -280, + -2203, + -1857, + -1577, + -1365, + -1205, + -1081, + -982, + -901, + -831, + -771, + -717, + -644, + -559, + -485, + -420, + -364, + -306, + -252, + -239, + -206, + -132, + -122, + -163, + -2224, + -1878, + -1598, + -1386, + -1225, + -1102, + -1003, + -921, + -852, + -792, + -737, + -665, + -580, + -505, + -441, + -385, + -326, + -271, + -222, + -224, + -176, + -121, + -114, +}; + +const Word32 c_pfMagLUT[8] = /* Q31 */ +{ + 0, 394599072, 775760576, 1130504448, 1446750336, 1713728896, 1922348544, 2065504896 +}; + +const Word32 c_pfP2RRealLUT[32] = /* Q31 */ +{ + INT_MIN, -2106220416, -1984016384, -1785567488, -1518500224, -1193078272, + -821806592, -418953280, -94, 418953088, 821806400, 1193077888, + 1518500224, 1785567360, 1984016128, 2106220288, 2147483647, 2106220288, + 1984016128, 1785567360, 1518500224, 1193077888, 821806400, 418953088, + -94, -418953280, -821806592, -1193078272, -1518500224, -1785567488, + -1984016384, -2106220416 +}; + +const Word32 c_pfP2RImagLUT[32] = /* Q31 */ +{ + 188, -418953248, -821806080, -1193077888, -1518500224, -1785567232, + -1984016128, -2106220288, INT_MIN, -2106220416, -1984016128, -1785567488, + -1518500224, -1193078016, -821806464, -418953280, 0, 418953280, + 821806464, 1193078016, 1518500224, 1785567488, 1984016128, 2106220416, + 2147483647, 2106220288, 1984016128, 1785567232, 1518500224, 1193077888, + 821806080, 418953248 +}; + +const Word32 c_pfWindowLUT[LCLD_PRED_WIN_LEN] = /* Q31 */ +{ + 190779840, 338280192, 610825408, 966922816, 1352359680, 1708457216, 1981002240, 2128502656, 2128502528, 1981002240, 1708456960, 1352359808, 966922624, 610825152, 338280192, 190779776 +}; +#endif diff --git a/lib_isar/isar_lcld_rom_tables.h b/lib_isar/isar_lcld_rom_tables.h new file mode 100644 index 000000000..4f1e80583 --- /dev/null +++ b/lib_isar/isar_lcld_rom_tables.h @@ -0,0 +1,245 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef _ISAR_LCLD_ROM_TABLES_H_ +#define _ISAR_LCLD_ROM_TABLES_H_ + +#include +#include "options.h" +#include "typedef.h" +#ifndef M_PI + +#define M_PI 3.14159265358979323846264338327950288f // todo: replace by EVS_PI +#define M_ONE_BY_PI_FX 10430 // 1/pi in Q15 + +#endif + +#define LCLD_BLOCKS_PER_FRAME ( 16 ) +#define LCLD_MAX_BLOCKS_PER_FRAME ( 16 ) +#define LCLD_BANDS ( 60 ) +#define LCLD_PRED_WIN_LEN ( 16 ) +#define LCLD_MAX_NUM_PRED_SUBSETS ( 8 ) +#define MAX_BANDS ( 23 ) +#define MAX_BANDS_48 ( 23 ) +#define DEF_BANDS_48 ( 22 ) + +#define ENV_MIN ( -64 ) +#define ENV_MAX ( 64 ) + +#define ENV0_BITS ( 7 ) + +#define ENV_DELTA_MIN ( -32 ) +#define ENV_DELTA_MIN_FX ( -1073741824 ) +#define ENV_DELTA_MAX ( 31 ) +#define ENV_DELTA_MAX_FX ( 1040187392 ) + +#define ENV_RECONSTRUCT_TABLE_SIZE ( 129 ) + +#define ENV_RECONSTRUCT_TABLE_CENTER ( 64 ) + +#define MIN_ALLOC ( 0 ) +#define MAX_ALLOC ( 31 ) + +#define ALLOC_OFFSET_SCALE ( 8 ) + +#define ALLOC_OFFSET_BITS ( 8 ) + +#define MIN_ALLOC_OFFSET ( -128 ) +#define MAX_ALLOC_OFFSET ( 127 ) +#define READ_LENGTH ( 4 ) + +#define ALLOC_TABLE_SIZE ( 32 ) + +#ifndef _PI_ +#define _PI_ ( 3.14159265358979f ) +#endif +#define PRED_MAX_VAL ( 12 ) +#define PRED_MIN_VAL ( -PRED_MAX_VAL ) +#define PRED_QUANT_FACTOR ( (float) PRED_MAX_VAL ) +#define PRED_QUANT_FACTOR_FX ( PRED_MAX_VAL ) +#define PRED_BAND0_BITS ( 5 ) + +#define PHASE_MAX_VAL ( 12 ) +#define PHASE_MIN_VAL ( -PHASE_MAX_VAL ) +#define PHASE_QUANT_FACTOR ( (float) PHASE_MAX_VAL / _PI_ ) +#define PHASE_QUANT_FACTOR_FX_Q29 ( 2050695826 ) +#define PHASE_DIFF_DIM ( 2 ) +#define PHASE_BAND0_BITS ( 5 ) + +#define PERCEPTUAL_MODEL_SLGAIN_SHIFT ( 8 ) + +// #define USE_DEMOD_TABLES + +#define HUFF_DEC_TABLE_SIZE ( 16 ) + +extern const int32_t c_aiNumLcldBandsPerBand[MAX_BANDS_48]; +extern const int32_t c_aiBandIdPerLcldBand[LCLD_BANDS]; +extern const float c_afRotRealImag[PRED_MAX_VAL - PRED_MIN_VAL + 1][2]; +extern const Word32 c_afRotRealImag_fx[PRED_MAX_VAL - PRED_MIN_VAL + 1][2]; +extern const Word16 c_aiDefaultTheta48_fx[MAX_BANDS_48]; +extern const int32_t c_aiDefaultTheta48[MAX_BANDS_48]; + +extern const float c_afScaleFactor[ALLOC_TABLE_SIZE]; +extern const float c_afInvScaleFactor[ALLOC_TABLE_SIZE]; +extern const Word32 c_afInvScaleFactor_fx[ALLOC_TABLE_SIZE]; +extern const float c_afRMSEnvReconstructTable[ENV_RECONSTRUCT_TABLE_SIZE]; +extern const int16_t c_afRMSEnvReconstructTable_exp[ENV_RECONSTRUCT_TABLE_SIZE]; +extern const int32_t c_aiQuantMaxValues[ALLOC_TABLE_SIZE]; +extern const int32_t c_aiHuffmanDim[ALLOC_TABLE_SIZE]; +extern const int32_t c_aiHuffmanMod[ALLOC_TABLE_SIZE]; +extern const Word32 c_aiHuffmanDim_fx[ALLOC_TABLE_SIZE]; +extern const Word32 c_aiHuffmanMod_fx[ALLOC_TABLE_SIZE]; +extern const Word32 c_afScaleFactor_fx[ALLOC_TABLE_SIZE]; +extern const Word32 c_aiQuantMaxValues_fx[ALLOC_TABLE_SIZE]; +extern const int32_t c_aiHuffmanSize[ALLOC_TABLE_SIZE]; + + +#define LOG_ADD_TABLE_LENGTH ( 512 ) + +extern const int32_t c_aiBandwidths48[MAX_BANDS_48]; +extern const Word16 c_aiLogAddTable_fx[LOG_ADD_TABLE_LENGTH]; +extern const Word16 c_aiBandwidthAdjust48_fx[MAX_BANDS_48]; +extern const int32_t c_aiLogAddTable[LOG_ADD_TABLE_LENGTH]; +extern const int32_t c_aiBandwidthAdjust48[MAX_BANDS_48]; + + +extern const Word16 c_aiAbsoluteThresh48_fx[MAX_BANDS_48]; +extern const Word16 c_aiDefaultTheta48_fx[MAX_BANDS_48]; +extern const Word16 c_aaiSpreadFunction48_fx[MAX_BANDS_48 * MAX_BANDS_48]; +extern const int32_t c_aiAbsoluteThresh48[MAX_BANDS_48]; +extern const int32_t c_aiDefaultTheta48[MAX_BANDS_48]; +extern const int32_t c_aaiSpreadFunction48[MAX_BANDS_48 * MAX_BANDS_48]; + + +#define PRED_QUNAT_FILTER_MAG_BITS ( 3 ) +#define PRED_QUANT_FILTER_PHASE_BITS ( 5 ) +#define PRED_QUANT_FILTER_MAG_MIN ( 0 ) +#define PRED_QUANT_FILTER_MAG_MAX ( 7 ) +#define PRED_QUANT_FILTER_PHASE_MIN ( -16 ) +#define PRED_QUANT_FILTER_PHASE_MAX ( 15 ) + +extern const uint16_t c_aauiLCLDHuffEnc1[16][2]; +extern const uint16_t c_aauiLCLDHuffEnc2[16][2]; +extern const uint16_t c_aauiLCLDHuffEnc3[25][2]; +extern const uint16_t c_aauiLCLDHuffEnc4[36][2]; +extern const uint16_t c_aauiLCLDHuffEnc5[36][2]; +extern const uint16_t c_aauiLCLDHuffEnc6[49][2]; +extern const uint16_t c_aauiLCLDHuffEnc7[64][2]; +extern const uint16_t c_aauiLCLDHuffEnc8[81][2]; +extern const uint16_t c_aauiLCLDHuffEnc9[100][2]; +extern const uint16_t c_aauiLCLDHuffEnc10[169][2]; +extern const uint16_t c_aauiLCLDHuffEnc11[196][2]; +extern const uint16_t c_aauiLCLDHuffEnc12[289][2]; +extern const uint16_t c_aauiLCLDHuffEnc13[324][2]; +extern const uint16_t c_aauiLCLDHuffEnc14[400][2]; +extern const uint16_t c_aauiLCLDHuffEnc15[576][2]; +extern const uint16_t c_aauiLCLDHuffEnc16[729][2]; +extern const uint16_t c_aauiLCLDHuffEnc17[729][2]; +extern const uint16_t c_aauiLCLDHuffEnc18[28][2]; +extern const uint16_t c_aauiLCLDHuffEnc19[29][2]; +extern const uint16_t c_aauiLCLDHuffEnc20[32][2]; +extern const uint16_t c_aauiLCLDHuffEnc21[37][2]; +extern const uint16_t c_aauiLCLDHuffEnc22[39][2]; +extern const uint16_t c_aauiLCLDHuffEnc23[46][2]; +extern const uint16_t c_aauiLCLDHuffEnc24[55][2]; +extern const uint16_t c_aauiLCLDHuffEnc25[65][2]; +extern const uint16_t c_aauiLCLDHuffEnc26[77][2]; +extern const uint16_t c_aauiLCLDHuffEnc27[91][2]; +extern const uint16_t c_aauiLCLDHuffEnc28[109][2]; +extern const uint16_t c_aauiLCLDHuffEnc29[129][2]; +extern const uint16_t c_aauiLCLDHuffEnc30[153][2]; +extern const uint16_t c_aauiLCLDHuffEnc31[181][2]; +extern const uint16_t c_aauiLCLDHuffEnc33[16][2]; +extern const uint16_t c_aauiLCLDHuffEnc34[16][2]; +extern const uint16_t c_aauiLCLDHuffEnc35[25][2]; +extern const uint16_t c_aauiLCLDHuffEnc36[36][2]; +extern const uint16_t c_aauiLCLDHuffEnc37[36][2]; +extern const uint16_t c_aauiLCLDHuffEnc38[49][2]; +extern const uint16_t c_aauiLCLDHuffEnc39[64][2]; +extern const uint16_t c_aauiLCLDHuffEnc40[81][2]; +extern const uint16_t c_aauiLCLDHuffEnc41[100][2]; +extern const uint16_t c_aauiLCLDHuffEnc42[169][2]; +extern const uint16_t c_aauiLCLDHuffEnc43[196][2]; +extern const uint16_t c_aauiLCLDHuffEnc44[289][2]; +extern const uint16_t c_aauiLCLDHuffEnc45[324][2]; +extern const uint16_t c_aauiLCLDHuffEnc46[400][2]; +extern const uint16_t c_aauiLCLDHuffEnc47[576][2]; +extern const uint16_t c_aauiLCLDHuffEnc48[729][2]; +extern const uint16_t c_aauiLCLDHuffEnc49[729][2]; +extern const uint16_t c_aauiLCLDHuffEnc50[28][2]; +extern const uint16_t c_aauiLCLDHuffEnc51[29][2]; +extern const uint16_t c_aauiLCLDHuffEnc52[32][2]; +extern const uint16_t c_aauiLCLDHuffEnc53[37][2]; +extern const uint16_t c_aauiLCLDHuffEnc54[39][2]; +extern const uint16_t c_aauiLCLDHuffEnc55[46][2]; +extern const uint16_t c_aauiLCLDHuffEnc56[55][2]; +extern const uint16_t c_aauiLCLDHuffEnc57[65][2]; +extern const uint16_t c_aauiLCLDHuffEnc58[77][2]; +extern const uint16_t c_aauiLCLDHuffEnc59[91][2]; +extern const uint16_t c_aauiLCLDHuffEnc60[109][2]; +extern const uint16_t c_aauiLCLDHuffEnc61[129][2]; +extern const uint16_t c_aauiLCLDHuffEnc62[153][2]; +extern const uint16_t c_aauiLCLDHuffEnc63[181][2]; +extern const uint16_t ( *c_apauiHuffEncTabels[2 * ALLOC_TABLE_SIZE] )[2]; +extern const uint32_t num_row_aauiLCLDHuff[2 * ALLOC_TABLE_SIZE]; + +#ifdef USE_DEMOD_TABLES +extern const int32_t c_aaiHuffDemod1[16][2]; +extern const int32_t c_aaiHuffDemod2[16][2]; +extern const int32_t c_aaiHuffDemod3[25][2]; +extern const int32_t c_aaiHuffDemod4[36][2]; +extern const int32_t c_aaiHuffDemod5[36][2]; +extern const int32_t c_aaiHuffDemod6[49][2]; +extern const int32_t c_aaiHuffDemod7[64][2]; +extern const int32_t c_aaiHuffDemod8[81][2]; +extern const int32_t c_aaiHuffDemod9[100][2]; +extern const int32_t c_aaiHuffDemod10[169][2]; +extern const int32_t c_aaiHuffDemod11[196][2]; +extern const int32_t c_aaiHuffDemod12[289][2]; +extern const int32_t c_aaiHuffDemod13[324][2]; +extern const int32_t c_aaiHuffDemod14[400][2]; +extern const int32_t c_aaiHuffDemod15[576][2]; +extern const int32_t c_aaiHuffDemod16[729][2]; +extern const int32_t c_aaiHuffDemod17[729][2]; +extern const int32_t ( *c_apaiDemodTables[ALLOC_TABLE_SIZE] )[2]; +#endif + +extern const uint32_t c_aaiRMSEnvHuffEnc[64][2]; +extern const uint32_t c_aaiRMSEnvHuffDec[13][HUFF_DEC_TABLE_SIZE]; + +extern const Word32 c_pfMagLUT[8]; /* Q31 */ +extern const Word32 c_pfP2RRealLUT[32]; /* Q31 */ +extern const Word32 c_pfP2RImagLUT[32]; /* Q31 */ +extern const Word32 c_pfWindowLUT[LCLD_PRED_WIN_LEN]; /* Q31 */ + + +#endif /* _TABLES_H_ */ diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h new file mode 100644 index 000000000..24f93b283 --- /dev/null +++ b/lib_isar/isar_prot.h @@ -0,0 +1,465 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_PROT_H +#define ISAR_PROT_H + + +#include "isar_stat.h" + +#ifdef SPLIT_REND_WITH_HEAD_ROT + +#include +#include "options.h" +#include "ivas_error.h" +#include "lib_isar_post_rend.h" +#include "enh64.h" + +Word32 ISAR_SPLIT_REND_BITStream_read_int32( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 bits ); + +void ISAR_SPLIT_REND_BITStream_write_int32( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 val, + const Word32 bits ); + +ivas_error isar_splitBinLCLDEncOpen( + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, + const int32_t iSampleRate, + const int16_t iChannels, + const int32_t iDataRate, + const int16_t iNumBlocks, + const int16_t iNumIterations ); + +ivas_error isar_splitBinRendPLCOpen( + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC, + int16_t iNumSubSets ); + +void isar_splitBinRendPLCClose( + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC ); +ivas_error isar_splitBinLCLDDecOpen( + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, + const Word32 iSampleRate, + const Word16 iChannels, + const Word16 iNumBlocks, + const Word16 iNumIterations ); +void isar_splitBinLCLDDecClose( + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec ); + +void isar_splitBinRendPLCsaveState( + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t num_chs, + const int16_t iNumBlocks, + const int16_t iNumIterations ); + +void isar_splitBinRendPLC_xf_fx( + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 num_chs, + const Word16 iNumBlocks, + const Word16 iNumIterations, + Word32 **ppiDecodingFailed, + Word32 **ppiDecodingFailedPrev, + Word16 exp ); + +void isar_splitBinRendPLC( + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 num_chs, + const Word16 iNumBlocks, + const Word16 iNumIterations, + Word32 **ppiDecodingFailed, + Word16 exp ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG +void isar_log_cldfb2wav_data( + float Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + HANDLE_CLDFB_FILTER_BANK *cldfbSyn, + const int16_t num_chs, + const int16_t num_freq_bands, + const int32_t output_Fs, + const int16_t start_slot_idx, + const int16_t md_band_idx, + const char *filename ); +#endif + +void isar_SplitRenderer_PostRenderer( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinPostRenderer, /* i/o: binaural renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ + Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ + const IVAS_QUATERNION Quaternion_act ); + +void isar_splitBinLCLDDecProcess( + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word32 Cldfb_Out_Real_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Imag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 *Q_cldfb_final, + const Word16 bfi ); + +void set_fix_rotation_mat_fx( + Word32 fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); +void set_fix_rotation_mat( + float fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + +void isar_splitBinLCLDEncClose( + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc ); +void isar_splitBinLCLDEncProcess( + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc, + Word32 Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word32 available_bits, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word16 *q_final ); + +void set_pose_types_fx( + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); +void set_pose_types( + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + +void isar_split_rend_init_huff_cfg( + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg ); + +ivas_error isar_splitBinPostRendOpen( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const int32_t output_Fs ); + +void isar_splitBinPostRendClose( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend ); + +void isar_SplitRenderer_getdiagdiff( + Word16 in_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 out_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + const Word16 sign, + const Word16 min_val, + const Word16 max_val ); + +void isar_renderSplitGetMultiBinPoseData_fx( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const ISAR_SPLIT_REND_ROT_AXIS rot_axis ); +void isar_renderSplitGetMultiBinPoseData( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const ISAR_SPLIT_REND_ROT_AXIS rot_axis ); + +void isar_split_rend_get_quant_params_fx( + const Word16 num_md_bands, + Word16 pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word32 pred_quantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word32 pred_1byquantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + const Word16 ro_flag, +#endif + Word16 *num_quant_strats +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + , + Word16 *num_complex_bands +#endif +); + +void isar_split_rend_get_quant_params( + const int16_t num_md_bands, + int16_t pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + float pred_quantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + float pred_1byquantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + int16_t *num_quant_strats, + int16_t *num_complex_bands ); + +void isar_splitBinPostRendMdDec_fx( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + , + BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend +#endif +); + +void Quat2EulerDegree( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float *yaw, /* o : yaw */ + float *pitch, /* o : pitch */ + float *roll /* o : roll */ +); + +void ivas_mat_mult_2by2_complex( + float in_re1[2][2], + float in_im1[2][2], + float in_re2[2][2], + float in_im2[2][2], + float out_re2[2][2], + float out_im2[2][2] ); + +void isar_mat_mult_2by2_complex_fx( + Word32 in_re1_fx[2][2], + Word16 exp_re1, + Word32 in_im1_fx[2][2], + Word16 exp_im1, + Word32 in_re2_fx[2][2], + Word16 exp_re2, + Word32 in_im2_fx[2][2], + Word16 exp_im2, + Word32 out_re2_fx[2][2], + Word16 *final_exp_re_1, + Word32 out_im2_fx[2][2], + Word16 *final_exp_im_1 ); + +void isar_rend_CldfbSplitPostRendProcess( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const IVAS_QUATERNION QuaternionPost, + Word32 Cldfb_RealBuffer_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + Word16 Q_cldfb_in, + Word32 output_fx[][L_FRAME48k], + Word16 *Q_out, + const Word16 cldfb_in_flag ); + +void isar_init_multi_bin_pose_data_fx( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + +/* Copy for encoder, to be removed */ +void isar_init_multi_bin_pose_data_fx_enc( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); +void isar_init_multi_bin_pose_data( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + +void isar_rend_CldfbSplitPreRendProcess( + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + const IVAS_QUATERNION headPosition, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_re, + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_im, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 target_md_bits, + const Word16 low_res_pre_rend_rot, + const Word16 ro_md_flag ); + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS +Word16 isar_renderSplitGetRot_axisNumBits( + const Word16 dof ); + +ISAR_SPLIT_REND_ROT_AXIS isar_renderSplitGetRot_axisFromCode( + const Word16 dof, + const Word16 code ); + +Word16 isar_renderSplitGetCodeFromRot_axis( + const Word16 dof, + const ISAR_SPLIT_REND_ROT_AXIS rot_axis, + Word16 *num_bits ); +#endif + +void isar_init_split_post_rend_handles( + ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper ); + +ivas_error isar_splitBinPreRendOpen( + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend, +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const int32_t output_Fs +#else + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData +#endif +); + +void isar_splitBinPreRendClose( + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend ); + +void isar_set_split_rend_ht_setup_fx( + SPLIT_REND_WRAPPER *hSplitrend, + IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES], + Word32 Rmat_fx[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] ); + + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +Word32 isar_get_lc3plus_bitrate( + const Word32 SplitRendBitRate, + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, + const Word16 split_prerender_frame_size_ms ); +#endif + +ivas_error isar_split_rend_validate_config( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const Word16 is_pcm_out ); + +Word32 isar_get_lcld_bitrate( + const Word32 SplitRendBitRate, + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode ); + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +Word8 isar_get_lc3plus_bitrate_id( + const Word32 SplitRendBitRate ); +#endif + +ivas_error splitRendLc3plusEncodeAndWrite( + SPLIT_REND_WRAPPER *hSplitBin, + ISAR_SPLIT_REND_BITS_HANDLE pBits, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const int32_t available_bits, +#else + const int32_t SplitRendBitRate, +#endif + Word32 *in[], + Word16 Q_sig ); + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +ivas_error isar_framesize_to_ms( + const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */ + Word16 *ms /* o : frame size in ms */ +); +#endif +Word32 isar_get_split_rend_md_target_brate( + const Word32 SplitRendBitRate, + const Word16 pcm_out_flag ); + +ivas_error isar_split_rend_choose_default_codec( + ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 *pIsar_frame_size_ms, /* i/o: pointer to isar frame size setting */ +#endif + Word16 *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ + const Word16 cldfb_in_flag, /* i : flag indicating rendering in TD */ + const Word16 pcm_out_flag, /* i : flag to indicate PCM output */ + const Word16 num_subframes /* i : number of subframes */ +); + +void ISAR_SPLIT_REND_BITStream_init( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 buf_len_bytes, + UWord8 *pbuf ); + +void isar_split_rend_huffman_dec_init_min_max_len( + isar_split_rend_huffman_cfg_t *p_huff_cfg ); + +Word16 wrap_a( + Word16 val, + const Word16 min_val, + const Word16 max_val ); +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +Word32 isar_get_lc3plus_size_from_id( + const Word8 SplitRendBitRateId, + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, + const Word16 split_prerender_frame_size_ms ); +#endif + +void isar_renderSplitUpdateNoCorrectionPoseData( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); + +Word32 get_bit( + const Word32 state, + const Word32 bit_id ); + +ivas_error split_renderer_open_lc3plus( + SPLIT_REND_WRAPPER *hSplitRendWrapper, + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const Word32 OutSampleRate, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const IVAS_RENDER_FRAMESIZE ivas_frame_size +#else + const int16_t num_subframes +#endif +); + +ISAR_POST_REND_AudioConfigType isar_getAudioConfigType( + const IVAS_AUDIO_CONFIG config ); + +void isar_init_split_rend_handles( + SPLIT_REND_WRAPPER *hSplitRendWrapper ); + +ivas_error isar_renderMultiTDBinToSplitBinaural( + SPLIT_REND_WRAPPER *hSplitBin, + const IVAS_QUATERNION headPosition, + const Word32 SplitRendBitRate, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const Word16 isar_frame_size_ms, +#endif + const Word16 codec_frame_size_ms, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word16 max_bands, + // float *in[], + Word32 *in_fx[], // Q11 + Word16 Q_sig, + const Word16 low_res_pre_rend_rot, + const Word16 pcm_out_flag, + const Word16 ro_md_flag ); + +void lc3plusTimeAlignCldfbPoseCorr( SPLIT_REND_WRAPPER *hSplitBin, + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 *Q_in ); + +#endif +void set16_fx( + Word16 y[], /* i/o: Vector to set */ + const Word16 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +); + +void set32_fx( + Word32 y[], /* i/o: Vector to set */ + const Word32 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +); + +Word16 ceil_log_2( + UWord64 val ); +/* clang-format on */ + +#endif /* IVAS_PROT_REND_H */ diff --git a/lib_isar/isar_rom_post_rend.c b/lib_isar/isar_rom_post_rend.c new file mode 100644 index 000000000..13a786b16 --- /dev/null +++ b/lib_isar/isar_rom_post_rend.c @@ -0,0 +1,196 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "cnst.h" +#include "isar_cnst.h" +#include +#include "wmc_auto.h" + +/* clang-format off */ + + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*----------------------------------------------------------------------* + * Binuaral split rendering ROM tables + *-----------------------------------------------------------------------*/ + +/* rotations in this array are relative to ref rotation */ +const Word32 ivas_split_rend_relative_yaw_pos_angles_fx[SPLIT_REND_MAX_YAW_ONLY_POSES] = { -62914560, 62914560 }; /* Q22 */ +const Word32 ivas_split_rend_relative_pitch_pos_angles_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES] = { 41943040, 41943040 }; /* Q22 */ +const Word32 ivas_split_rend_relative_roll_pos_angles_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES] = { 41943040, 41943040 }; /* Q22 */ +const float ivas_split_rend_relative_yaw_pos_angles[SPLIT_REND_MAX_YAW_ONLY_POSES] = {-15.0f, 15.0f}; +const float ivas_split_rend_relative_pitch_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {10.0f, 10.0f}; +const float ivas_split_rend_relative_roll_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {10.0f, 10.0f}; +const float ivas_split_rend_relative_one_axis_pos_angles[SPLIT_REND_MAX_ONE_AXIS_MD_POSES] = {-15.0f, 15.0f}; + +const Word32 ivas_split_rend_relative_yaw_pos_angles_hq_fx[SPLIT_REND_MAX_YAW_ONLY_POSES] = { -62914560, 62914560 }; /* Q22 */ +const Word32 ivas_split_rend_relative_pitch_pos_angles_hq_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES] = { -62914560, 62914560 }; /* Q22 */ +const Word32 ivas_split_rend_relative_roll_pos_angles_hq_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES] = { -62914560, 62914560 }; /* Q22 */ +const float ivas_split_rend_relative_yaw_pos_angles_hq[SPLIT_REND_MAX_YAW_ONLY_POSES] = {-15.0f, 15.0f}; +const float ivas_split_rend_relative_pitch_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {-15.0f, 15.0f}; +const float ivas_split_rend_relative_roll_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES] = {-15.0f, 15.0f}; +const float ivas_split_rend_relative_one_axis_pos_angles_hq[SPLIT_REND_MAX_ONE_AXIS_MD_POSES] = {-15.0f, 15.0f}; + +/* Values in degrees : -30, -22.5, -15, 0, 15, 22.5 and 30 */ +const Word32 ivas_split_rend_fix_pos_rot_mat_cos_fx[4] = { ONE_IN_Q31, 2074309917, 1984016189, 1859775393 }; /* Q31 */ + +const int16_t isar_split_rend_band_grouping[MAX_SPLIT_REND_MD_BANDS + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 20, 25, 30, 35, 40, 50, 60 +}; + +const int32_t ivas_split_rend_huff_p_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3] = +{ + {0,8,252},{1,8,253},{2,7,124},{3,6,60},{4,5,28},{5,4,12}, + {6,3,4},{7,1,0},{8,3,5},{9,4,13},{10,5,29},{11,6,61}, + {12,7,125},{13,8,254},{14,8,255} +}; + +const int32_t ivas_split_rend_huff_p_d_diff_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3] = +{ + { 0, 1, 0 },{ 1, 2, 2 },{ 2, 3, 6 },{ 3, 4, 14 }, + { 4, 5, 30 },{ 5, 6, 62 },{ 6, 7, 126 },{ 7, 8, 254 }, + { 8, 9, 510 },{ 9, 10, 1022 },{ 10, 11, 2046 },{ 11, 12, 4094 }, + { 12, 13, 8190 },{ 13, 14, 16382 },{ 14, 14, 16383 } +}; + +const int32_t ivas_split_rend_huff_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3] = +{ + { 0, 1, 0 },{ 1, 2, 2 },{ 2, 3, 6 },{ 3, 4, 14 }, + { 4, 5, 30 },{ 5, 6, 62 },{ 6, 7, 126 },{ 7, 8, 254 }, + { 8, 9, 510 },{ 9, 10, 1022 },{ 10, 11, 2046 },{ 11, 12, 4094 }, + { 12, 13, 8190 },{ 13, 14, 16382 },{ 14, 14, 16383 } +}; + +const int32_t ivas_split_rend_huff_pred63_consts[ISAR_SPLIT_REND_PRED_63QUANT_PNTS][3] = +{ + {-31,11,2040}, + {-30,11,2041}, + {-29,11,2042}, + {-28,11,2043}, + {-27,10,1012}, + {-26,10,1013}, + {-25,10,1014}, + {-24,10,1015}, + {-23,9,498}, + {-22,9,499}, + {-21,9,500}, + {-20,9,501}, + {-19,8,242}, + {-18,8,243}, + {-17,8,244}, + {-16,8,245}, + {-15,7,112}, + {-14,7,113}, + {-13,7,114}, + {-12,7,115}, + {-11,6,48}, + {-10,6,49}, + {-9,6,50}, + {-8,6,51}, + {-7,5,16}, + {-6,5,17}, + {-5,5,18}, + {-4,5,19}, + {-3,4,2}, + {-2,4,3}, + {-1,4,4}, + {0,3,0}, + {1,4,5}, + {2,4,6}, + {3,4,7}, + {4,5,20}, + {5,5,21}, + {6,5,22}, + {7,5,23}, + {8,6,52}, + {9,6,53}, + {10,6,54}, + {11,6,55}, + {12,7,116}, + {13,7,117}, + {14,7,118}, + {15,7,119}, + {16,7,120}, + {17,8,246}, + {18,8,247}, + {19,8,248}, + {20,9,502}, + {21,9,503}, + {22,9,504}, + {23,9,505}, + {24,10,1016}, + {25,10,1017}, + {26,10,1018}, + {27,10,1019}, + {28,11,2044}, + {29,11,2045}, + {30,11,2046}, + {31,11,2047}, +}; + +const int32_t ivas_split_rend_huff_pred31_consts[ISAR_SPLIT_REND_PRED_31QUANT_PNTS][3] = +{ + {-15,10,1020},{-14,10,1021},{-13,9,506},{-12,9,507}, + {-11,8,250},{-10,8,251},{-9,7,120},{-8,7,121}, + {-7,6,56},{-6,6,57},{-5,5,24},{-4,5,25},{-3,4,8}, + {-2,4,9},{-1,3,2},{0,2,0},{1,3,3}, + {2,4,10},{3,4,11},{4,5,26},{5,5,27}, + {6,6,58},{7,6,59},{8,7,122},{9,7,123}, + {10,7,124},{11,8,252},{12,9,508},{13,9,509}, + {14,10,1022},{15,10,1023}, +}; + +const int32_t ivas_split_rend_huff_roll_pred_consts[ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS][3] = +{ + {-15,10,1020},{-14,10,1021},{-13,9,506},{-12,9,507}, + {-11,8,250},{-10,8,251},{-9,7,120},{-8,7,121}, + {-7,6,56},{-6,6,57},{-5,5,24},{-4,5,25},{-3,4,8}, + {-2,4,9},{-1,3,2},{0,2,0},{1,3,3}, + {2,4,10},{3,4,11},{4,5,26},{5,5,27}, + {6,6,58},{7,6,59},{8,7,122},{9,7,123}, + {10,7,124},{11,8,252},{12,9,508},{13,9,509}, +{14,10,1022},{15,10,1023}, +}; + +#endif + +/* Tables for split renderer fixed converison */ +const Word16 fade_table_fx[4] = +{ 8192, 16384, 24576, 32767 }; + +/* clang-format on */ diff --git a/lib_isar/isar_rom_post_rend.h b/lib_isar/isar_rom_post_rend.h new file mode 100644 index 000000000..2bfac9140 --- /dev/null +++ b/lib_isar/isar_rom_post_rend.h @@ -0,0 +1,82 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_ROM_POST_REND_H +#define ISAR_ROM_POST_REND_H + +#include +#include "options.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "cnst.h" +#include "isar_cnst.h" + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*----------------------------------------------------------------------* + * Binuaral split rendering ROM tables + *-----------------------------------------------------------------------*/ + +extern const Word32 ivas_split_rend_relative_yaw_pos_angles_fx[SPLIT_REND_MAX_YAW_ONLY_POSES]; +extern const Word32 ivas_split_rend_relative_pitch_pos_angles_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const Word32 ivas_split_rend_relative_roll_pos_angles_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const float ivas_split_rend_relative_yaw_pos_angles[SPLIT_REND_MAX_YAW_ONLY_POSES]; +extern const float ivas_split_rend_relative_pitch_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const float ivas_split_rend_relative_roll_pos_angles[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const float ivas_split_rend_relative_one_axis_pos_angles[SPLIT_REND_MAX_ONE_AXIS_MD_POSES]; +extern const float ivas_split_rend_relative_one_axis_pos_angles_hq[SPLIT_REND_MAX_ONE_AXIS_MD_POSES]; + +extern const Word32 ivas_split_rend_relative_yaw_pos_angles_hq_fx[SPLIT_REND_MAX_YAW_ONLY_POSES]; +extern const Word32 ivas_split_rend_relative_pitch_pos_angles_hq_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const Word32 ivas_split_rend_relative_roll_pos_angles_hq_fx[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const float ivas_split_rend_relative_yaw_pos_angles_hq[SPLIT_REND_MAX_YAW_ONLY_POSES]; +extern const float ivas_split_rend_relative_pitch_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES]; +extern const float ivas_split_rend_relative_roll_pos_angles_hq[SPLIT_REND_MAX_PITCH_ONLY_POSES]; + +/* Values in degrees : -30, -22.5, -15, 0, 15, 22.5 and 30 */ +extern const Word32 ivas_split_rend_fix_pos_rot_mat_cos_fx[4]; /* Q31 */ + +extern const float ivas_split_rend_relative_pos_angles[MAX_HEAD_ROT_POSES][3]; +extern const int16_t isar_split_rend_band_grouping[MAX_SPLIT_REND_MD_BANDS + 1]; +extern const int32_t ivas_split_rend_huff_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3]; +extern const int32_t ivas_split_rend_huff_pred63_consts[ISAR_SPLIT_REND_PRED_31QUANT_PNTS][3]; +extern const int32_t ivas_split_rend_huff_pred31_consts[ISAR_SPLIT_REND_PRED_31QUANT_PNTS][3]; +extern const int32_t ivas_split_rend_huff_roll_pred_consts[ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS][3]; +extern const int32_t ivas_split_rend_huff_p_d_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3]; +extern const int32_t ivas_split_rend_huff_p_d_diff_consts[ISAR_SPLIT_REND_D_QUANT_PNTS][3]; +extern const int32_t split_rend_brate_tbl[]; +#endif + +/* Tables for fixed point conversion */ +extern const Word16 fade_table_fx[4]; + +#endif diff --git a/lib_isar/isar_splitRend_lcld_dec.c b/lib_isar/isar_splitRend_lcld_dec.c new file mode 100644 index 000000000..7e5c3e2bb --- /dev/null +++ b/lib_isar/isar_splitRend_lcld_dec.c @@ -0,0 +1,284 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "isar_prot.h" +#include "ivas_prot.h" +#include "prot.h" +#include "control.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +/*------------------------------------------------------------------------- + * Function isar_splitBinLCLDDecOpen() + * + * + *------------------------------------------------------------------------*/ +ivas_error isar_splitBinLCLDDecOpen( + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec, + const Word32 iSampleRate, + const Word16 iChannels, + const Word16 iNumBlocks, + const Word16 iNumIterations ) +{ + int16_t n; + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE splitBinLCLDDec; + ivas_error error; + + IF( ( splitBinLCLDDec = (ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE) malloc( sizeof( ISAR_BIN_HR_SPLIT_LCLD_DEC ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + + splitBinLCLDDec->pLcld_dec = NULL; /* place holder for CLDFB decoder handle */ + + splitBinLCLDDec->iChannels = iChannels; + + IF( ( error = CreateLCLDDecoder( &splitBinLCLDDec->psLCLDDecoder, iSampleRate, iChannels, iNumBlocks, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( splitBinLCLDDec->pppfDecLCLDReal_fx = (Word32 ***) malloc( iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( splitBinLCLDDec->pppfDecLCLDImag_fx = (Word32 ***) malloc( iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + + FOR( n = 0; n < splitBinLCLDDec->iChannels; n++ ) + { + IF( ( splitBinLCLDDec->pppfDecLCLDReal_fx[n] = (Word32 **) malloc( CLDFB_NO_COL_MAX * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + IF( ( splitBinLCLDDec->pppfDecLCLDImag_fx[n] = (Word32 **) malloc( CLDFB_NO_COL_MAX * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD decoder Module \n" ) ); + } + } +#ifdef CLDFB_DEBUG + splitBinLCLDDec->numFrame = 0; + char cldfbFilename[50] = "cldfb_out.bin"; + if ( ( splitBinLCLDDec->cldfbOut = fopen( cldfbFilename, "wb" ) ) == NULL ) + { + fprintf( stderr, "Error: CLDFB bitstream file %s could not be opened\n\n", cldfbFilename ); + exit( -1 ); + } + int16_t num_bands = CLDFB_NO_CHANNELS_MAX; + fwrite( &iChannels, sizeof( int16_t ), 1, splitBinLCLDDec->cldfbOut ); + fwrite( &num_bands, sizeof( int16_t ), 1, splitBinLCLDDec->cldfbOut ); +#endif + + IF( ( error = isar_splitBinRendPLCOpen( &splitBinLCLDDec->hSplitRendPLC, GetNumSubSets( splitBinLCLDDec->psLCLDDecoder ) ) ) != IVAS_ERR_OK ) + { + return error; + } + splitBinLCLDDec->iNumBlocks = iNumBlocks; + splitBinLCLDDec->iNumIterations = iNumIterations; + + *hSplitBinLCLDDec = splitBinLCLDDec; + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * Function isar_splitBinLCLDDecClose() + * + * + *------------------------------------------------------------------------*/ + +void isar_splitBinLCLDDecClose( + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE *hSplitBinLCLDDec ) +{ + Word16 n; + + IF( ( *hSplitBinLCLDDec ) != NULL ) + { + IF( ( *hSplitBinLCLDDec )->psLCLDDecoder != NULL ) + { + DeleteLCLDDecoder( ( *hSplitBinLCLDDec )->psLCLDDecoder ); + } + + FOR( n = 0; n < ( *hSplitBinLCLDDec )->iChannels; n++ ) + { + free( ( *hSplitBinLCLDDec )->pppfDecLCLDReal_fx[n] ); + free( ( *hSplitBinLCLDDec )->pppfDecLCLDImag_fx[n] ); + } + free( ( *hSplitBinLCLDDec )->pppfDecLCLDReal_fx ); + free( ( *hSplitBinLCLDDec )->pppfDecLCLDImag_fx ); + +#ifdef CLDFB_DEBUG + if ( ( *hSplitBinLCLDDec )->cldfbOut != NULL ) + { + fclose( ( *hSplitBinLCLDDec )->cldfbOut ); + } +#endif + isar_splitBinRendPLCClose( &( *hSplitBinLCLDDec )->hSplitRendPLC ); + + free( *hSplitBinLCLDDec ); + *hSplitBinLCLDDec = NULL; + } + + return; +} + +/*------------------------------------------------------------------------- + * Function isar_splitBinLCLDDecProcess() + * + * + *------------------------------------------------------------------------*/ +void isar_splitBinLCLDDecProcess( + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word32 Cldfb_Out_Real_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Imag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 *Q_cldfb_final, + const Word16 bfi ) +{ + Word16 k, n; + Word16 itr; + *Q_cldfb_final = 11; + push_wmops( "isar_splitBinLCLDDecProcess" ); + + assert( hSplitBinLCLDDec != NULL ); + assert( Cldfb_Out_Real_fx != NULL ); + assert( Cldfb_Out_Imag_fx != NULL ); + assert( pBits != NULL ); +#ifdef CLDFB_DEBUG + printf( "Bytes read = %d\n", iBytesWritten ); +#endif + IF( !bfi ) + { + FOR( itr = 0; itr < hSplitBinLCLDDec->iNumIterations; itr++ ) + { + /* Initialized with zeros....... */ + FOR( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + { + FOR( k = 0; k < hSplitBinLCLDDec->iNumBlocks; k++ ) + { + hSplitBinLCLDDec->pppfDecLCLDReal_fx[n][k] = Cldfb_Out_Real_fx[n][hSplitBinLCLDDec->iNumBlocks * itr + k]; + hSplitBinLCLDDec->pppfDecLCLDImag_fx[n][k] = Cldfb_Out_Imag_fx[n][hSplitBinLCLDDec->iNumBlocks * itr + k]; + set_l( hSplitBinLCLDDec->pppfDecLCLDReal_fx[n][k], 0, CLDFB_NO_CHANNELS_MAX ); + set_l( hSplitBinLCLDDec->pppfDecLCLDImag_fx[n][k], 0, CLDFB_NO_CHANNELS_MAX ); + } + } + + Word16 Q_in = 14; + DecodeLCLDFrame( hSplitBinLCLDDec->psLCLDDecoder, pBits, hSplitBinLCLDDec->pppfDecLCLDReal_fx, hSplitBinLCLDDec->pppfDecLCLDImag_fx, Q_in, Q_cldfb_final ); + +#ifdef CLDFB_DEBUG + printf( "Frame Decoded = %d\n", ++hSplitBinLCLDDec->numFrame ); + int16_t writeByte = 0; + for ( k = 0; k < CLDFB_NO_COL_MAX; k++ ) + { + for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + { + for ( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + { + writeByte = fwrite( &hSplitBinLCLDDec->pppfDecLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDDec->cldfbOut ); + if ( writeByte != 1 ) + exit( -1 ); + writeByte = fwrite( &hSplitBinLCLDDec->pppfDecLCLDImag[n][k][b], sizeof( float ), 1, hSplitBinLCLDDec->cldfbOut ); + if ( writeByte != 1 ) + exit( -1 ); + } + } + } +#endif + IF( AnyDecodingFailed( hSplitBinLCLDDec->psLCLDDecoder ) ) + { + IF( NE_16( *Q_cldfb_final, 11 ) ) + { + FOR( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + { + FOR( k = 0; k < hSplitBinLCLDDec->iNumBlocks; k++ ) + { + FOR( Word16 j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hSplitBinLCLDDec->pppfDecLCLDReal_fx[n][k][j] = L_shl_r( hSplitBinLCLDDec->pppfDecLCLDReal_fx[n][k][j], sub( 11, *Q_cldfb_final ) ); // Q11 + hSplitBinLCLDDec->pppfDecLCLDImag_fx[n][k][j] = L_shl_r( hSplitBinLCLDDec->pppfDecLCLDImag_fx[n][k][j], sub( 11, *Q_cldfb_final ) ); // Q11 + } + } + } + *Q_cldfb_final = 11; + } + /* continue concealing */ + isar_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real_fx, Cldfb_Out_Imag_fx, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations, GetDecodingFailedStatus( hSplitBinLCLDDec->psLCLDDecoder ), *Q_cldfb_final ); + } + IF( AnyDecodingFailedPrev( hSplitBinLCLDDec->psLCLDDecoder ) ) + { + IF( NE_16( *Q_cldfb_final, 11 ) ) + { + FOR( n = 0; n < hSplitBinLCLDDec->iChannels; n++ ) + { + FOR( k = 0; k < hSplitBinLCLDDec->iNumBlocks; k++ ) + { + FOR( Word16 j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) + { + hSplitBinLCLDDec->pppfDecLCLDReal_fx[n][k][j] = L_shl_r( hSplitBinLCLDDec->pppfDecLCLDReal_fx[n][k][j], sub( 11, *Q_cldfb_final ) ); // Q11 + hSplitBinLCLDDec->pppfDecLCLDImag_fx[n][k][j] = L_shl_r( hSplitBinLCLDDec->pppfDecLCLDImag_fx[n][k][j], sub( 11, *Q_cldfb_final ) ); // Q11 + } + } + } + *Q_cldfb_final = 11; + } + /* cross-fade recovered frame into good frame */ + isar_splitBinRendPLC_xf_fx( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real_fx, Cldfb_Out_Imag_fx, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations, GetDecodingFailedStatus( hSplitBinLCLDDec->psLCLDDecoder ), GetDecodingFailedPrevStatus( hSplitBinLCLDDec->psLCLDDecoder ), *Q_cldfb_final ); + } + } + } + ELSE + { + /* set states in decoder */ + SetDecodingUnresolved( hSplitBinLCLDDec->psLCLDDecoder ); + + /* do PLC for lost split renderer frame */ + isar_splitBinRendPLC( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real_fx, Cldfb_Out_Imag_fx, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations, GetDecodingFailedStatus( hSplitBinLCLDDec->psLCLDDecoder ), *Q_cldfb_final ); + } + + /* save PLC state */ + isar_splitBinRendPLCsaveState( hSplitBinLCLDDec->hSplitRendPLC, Cldfb_Out_Real_fx, Cldfb_Out_Imag_fx, (int16_t) hSplitBinLCLDDec->iChannels, hSplitBinLCLDDec->iNumBlocks, hSplitBinLCLDDec->iNumIterations ); + hSplitBinLCLDDec->hSplitRendPLC->CldfbPLC_state.Q_Prev_Bin_fx = *Q_cldfb_final; + move16(); + pop_wmops(); + + return; +} +#endif diff --git a/lib_isar/isar_splitRend_lcld_enc.c b/lib_isar/isar_splitRend_lcld_enc.c new file mode 100644 index 000000000..0f442a2f2 --- /dev/null +++ b/lib_isar/isar_splitRend_lcld_enc.c @@ -0,0 +1,239 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "isar_prot.h" +#include "ivas_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + +/*------------------------------------------------------------------------- + * Function isar_splitBinLCLDEncOpen() + * + * + *------------------------------------------------------------------------*/ +ivas_error isar_splitBinLCLDEncOpen( + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc, + const Word32 iSampleRate, + const Word16 iChannels, + const Word32 iDataRate, + const Word16 iNumBlocks, + const Word16 iNumIterations ) +{ + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE splitBinLCLDEnc; + ivas_error error; + + IF( ( splitBinLCLDEnc = (ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE) malloc( sizeof( ISAR_BIN_HR_SPLIT_LCLD_ENC ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + splitBinLCLDEnc->pLcld_enc = NULL; /* place holder for CLDFB encoder handle*/ + + splitBinLCLDEnc->iChannels = iChannels; + IF( ( error = CreateLCLDEncoder( &( splitBinLCLDEnc->psLCLDEncoder ), iSampleRate, iChannels, iDataRate, 1, iNumBlocks, (Word16) CLDFB_NO_COL_MAX / iNumBlocks, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( splitBinLCLDEnc->pppfLCLDReal_fx = (Word32 ***) malloc( iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( splitBinLCLDEnc->pppfLCLDImag_fx = (Word32 ***) malloc( iChannels * sizeof( Word32 ** ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + + FOR( Word16 n = 0; n < splitBinLCLDEnc->iChannels; n++ ) + { + IF( ( splitBinLCLDEnc->pppfLCLDReal_fx[n] = (Word32 **) malloc( CLDFB_NO_COL_MAX * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + IF( ( splitBinLCLDEnc->pppfLCLDImag_fx[n] = (Word32 **) malloc( CLDFB_NO_COL_MAX * sizeof( Word32 * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LCLD encoder Module \n" ) ); + } + } + + splitBinLCLDEnc->iNumIterations = iNumIterations; + splitBinLCLDEnc->iNumBlocks = iNumBlocks; + +#ifdef CLDFB_DEBUG + splitBinLCLDEnc->numFrame = 0; + char cldfbFilename[50] = "cldfb_in_ref.qmf"; + if ( ( splitBinLCLDEnc->cldfbIn = fopen( cldfbFilename, "rb" ) ) == NULL ) + { + fprintf( stderr, "Error: CLDFB bitstream file %s could not be opened\n\n", cldfbFilename ); + exit( -1 ); + } + int16_t chan, band; + fread( &chan, sizeof( int16_t ), 1, splitBinLCLDEnc->cldfbIn ); + fread( &band, sizeof( int16_t ), 1, splitBinLCLDEnc->cldfbIn ); +#endif + + *hSplitBinLCLDEnc = splitBinLCLDEnc; + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * Function isar_splitBinLCLDEncClose() + * + * + *------------------------------------------------------------------------*/ + +void isar_splitBinLCLDEncClose( + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc ) +{ + IF( ( *hSplitBinLCLDEnc ) != NULL ) + { + DeleteLCLDEncoder( ( *hSplitBinLCLDEnc )->psLCLDEncoder ); + + FOR( int16_t n = 0; n < ( *hSplitBinLCLDEnc )->iChannels; n++ ) + { + free( ( *hSplitBinLCLDEnc )->pppfLCLDReal_fx[n] ); + free( ( *hSplitBinLCLDEnc )->pppfLCLDImag_fx[n] ); + } + free( ( *hSplitBinLCLDEnc )->pppfLCLDReal_fx ); + free( ( *hSplitBinLCLDEnc )->pppfLCLDImag_fx ); +#ifdef CLDFB_DEBUG + if ( ( *hSplitBinLCLDEnc )->cldfbIn != NULL ) + { + fclose( ( *hSplitBinLCLDEnc )->cldfbIn ); + } +#endif + + free( *hSplitBinLCLDEnc ); + *hSplitBinLCLDEnc = NULL; + } + + return; +} + +/*------------------------------------------------------------------------- + * Function isar_splitBinLCLDEncProcess() + * + * + *------------------------------------------------------------------------*/ +void isar_splitBinLCLDEncProcess( + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc, + Word32 Cldfb_In_Real_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_Imag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word32 available_bits, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word16 *q_final ) +{ + Word32 iBitsWritten, itr, available_bits_itr, rem_itr, available_bits_local; + push_wmops( "isar_splitBinLCLDEncProcess" ); + assert( hSplitBinLCLDEnc != NULL ); + assert( Cldfb_In_Real_fx != NULL ); + assert( Cldfb_In_Imag_fx != NULL ); + assert( pBits != NULL ); + + available_bits_local = available_bits; + move32(); + Word16 tmp, tmp_e; + /* A conversion is needed for the 3d pointer interface here ........ */ + FOR( itr = 0; itr < hSplitBinLCLDEnc->iNumIterations; itr++ ) + { + + rem_itr = L_sub( hSplitBinLCLDEnc->iNumIterations, itr ); + tmp = BASOP_Util_Divide3232_Scale( available_bits_local, rem_itr, &tmp_e ); + available_bits_itr = shr( tmp, sub( 15, tmp_e ) ); // Q0 + // available_bits_itr = available_bits_local / rem_itr; + FOR( Word32 n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + { + FOR( Word32 k = 0; k < hSplitBinLCLDEnc->iNumBlocks; k++ ) + { + hSplitBinLCLDEnc->pppfLCLDReal_fx[n][k] = Cldfb_In_Real_fx[n][hSplitBinLCLDEnc->iNumBlocks * itr + k]; + hSplitBinLCLDEnc->pppfLCLDImag_fx[n][k] = Cldfb_In_Imag_fx[n][hSplitBinLCLDEnc->iNumBlocks * itr + k]; + } + } +#ifdef CLDFB_DEBUG + int16_t readByte = 0; + for ( int16_t k = 0; k < hSplitBinLCLDEnc->iNumBlocks; k++ ) + { + for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + { + for ( int16_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + { + readByte = fread( &hSplitBinLCLDEnc->pppfLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); + if ( readByte != 1 ) + break; + readByte = fread( &hSplitBinLCLDEnc->pppfLCLDReal[n][k][b], sizeof( float ), 1, hSplitBinLCLDEnc->cldfbIn ); + } + } + } + + if ( readByte == 1 ) + { + printf( "Frame Read = %d\n", ++hSplitBinLCLDEnc->numFrame ); + } + else + { + printf( "Writing zeroes...\n" ); + for ( int16_T k = 0; k < hSplitBinLCLDEnc->iNumBlocks; k++ ) + { + for ( int16_t b = 0; b < CLDFB_NO_CHANNELS_MAX; b++ ) + { + for ( int16_t n = 0; n < hSplitBinLCLDEnc->iChannels; n++ ) + { + hSplitBinLCLDEnc->pppfLCLDReal[n][k][b] = 0.f; + hSplitBinLCLDEnc->pppfLCLDImag[n][k][b] = 0.f; + } + } + } + } +#endif + EncodeLCLDFrame( hSplitBinLCLDEnc->psLCLDEncoder, hSplitBinLCLDEnc->pppfLCLDReal_fx, hSplitBinLCLDEnc->pppfLCLDImag_fx, &iBitsWritten, available_bits_itr, pBits, q_final ); + + available_bits_local = L_sub( available_bits_local, iBitsWritten ); +#ifdef DEBUGGING + assert( available_bits_local >= 0 ); +#endif + +#ifdef CLDFB_DEBUG + printf( "Bits written = %d\n", iBitsWritten ); +#endif + } + pop_wmops(); + + return; +} +#endif diff --git a/lib_isar/isar_splitRendererPLC.c b/lib_isar/isar_splitRendererPLC.c new file mode 100644 index 000000000..152fe52f3 --- /dev/null +++ b/lib_isar/isar_splitRendererPLC.c @@ -0,0 +1,1316 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "ivas_prot.h" +#include "prot.h" +#include "isar_cnst.h" +#include "isar_prot.h" +#include "enh64.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" +#include "prot_fx2.h" +#include "basop_util.h" +#include "basop_mpy.h" +#include "enh64.h" + +/*------------------------------------------------------------------------- + * Local constants + *------------------------------------------------------------------------*/ +#define PI_CONST ( 341782638 ) // Q31 +#define DO_PERTURB 1 +#define PH_PERT_ONLY 1 +#define START_VAL_AVG_LEN 2 +#define SR_PLC_FADE_START 10 /* start fading at this number of bad frames in row */ +#define SR_PLC_MUTE 30 /* Total mute at this number of bad frames in row */ +#define SR_PLC_FADE_DEGREE -3 /* fading degree per frame in dB */ +#define SRHO_THRESH ( 2.f / 3.f * 0.1f ) +#define SRHO_THRESH_FX ( 143165584 ) +#define STH_THRESH_FX ( 749613227 ) +#define STH_THRESH ( 2.f / 3.f * PI2 / 12 ) +#define PLC_FADE_CNST SR_PLC_FADE_START *CLDFB_NO_COL_MAX +#define PLC_MUTE_CNST SR_PLC_MUTE *CLDFB_NO_COL_MAX +Word32 xf_alp_tab[CLDFB_PLC_XF] = { 1431655680, 715827840 }; +static Word16 find_guarded_bits_fx( Word32 n ) +{ + return n <= 1 ? 0 : n <= 2 ? 1 + : n <= 4 ? 2 + : n <= 8 ? 3 + : n <= 16 ? 4 + : n <= 32 ? 5 + : n <= 64 ? 6 + : n <= 128 ? 7 + : n <= 256 ? 8 + : n <= 512 ? 9 + : n <= 1024 ? 10 + : n <= 2048 ? 11 + : n <= 4096 ? 12 + : n <= 8192 ? 13 + : n <= 16384 ? 14 + : 15; +} + +/*------------------------------------------------------------------------- + * Function adaptive_polar_ext_plc() + * + * + *------------------------------------------------------------------------*/ +static void adaptive_polar_ext_plc_fx( + const Word32 *prev_real_fx, + const Word32 *prev_imag_fx, + Word32 *rec_real_fx, + Word32 *rec_imag_fx, + Word16 *rec_real_exp, + Word16 *rec_imag_exp +#if CLDFB_PLC_XF > 0 + , + Word32 xf_alp_fx[CLDFB_PLC_XF], + Word32 xf_bet_fx[CLDFB_PLC_XF] +#endif + , + Word16 exp, + const Word16 iNumCols ) + +{ + /*TODO: Add basops and instrumentation where ever possible*/ + Word32 uth_fx[CLDFB_NO_COL_MAX], urh_fx[CLDFB_NO_COL_MAX]; + Word64 uthu_fx[CLDFB_NO_COL_MAX], drho_fx, srho_fx, diff_fx, dth_fx, sth_fx, ph_adj_fx, rat_real_fx, rat_imag_fx; + Word32 ph_diff_fx, ph_adj_t_fx, quot_fx, dth32, fac_real_fx, fac_imag_fx, rat_real32_fx, rat_imag32_fx, abs2inv_fx; + Word16 srho_q, sth_q, dth16, drho_q, rat_real_q, rat_imag_q, temp_16, rat_real_sum_q, rat_imag_sum_q, start_q, fac_real_q, fac_imag_q; + Word64 Ruu_real_fx[2], Ruu_imag_fx[2], abs_fac_fx; + Word32 Ruu_real_fx_1, Ruu_imag_fx_1, Ruu_real_fx_0, abs_fac_32, abs_fac_powj_32, comp_fac_fx; + Word16 Ruu_real_fx_1_q, Ruu_imag_fx_1_q, Ruu_real_fx_0_q, dth_q, urh_exp[CLDFB_NO_COL_MAX]; + Word32 fac_ph_real_fx, fac_ph_imag_fx, abs_temp_fx; + Word32 start_real_fx, start_imag_fx, fac_powj_real_fx, fac_powj_imag_fx, temp_fx; + Word32 k, j; + Word16 quot_exp[CLDFB_NO_COL_MAX]; + Word16 drho_exp[CLDFB_NO_COL_MAX]; + Word16 srho_exp[CLDFB_NO_COL_MAX]; + /* Word16 rec_real_exp[CLDFB_NO_COL_MAX + CLDFB_PLC_XF]; + Word16 rec_imag_exp[CLDFB_NO_COL_MAX + CLDFB_PLC_XF];*/ + /* reset of accumulators */ + ph_adj_fx = 0; + drho_fx = 0; + srho_fx = 0; + dth_fx = 0; + sth_fx = 0; + Word16 sqrt_exp = 0, sqrt_exp1; + Word32 temp_32; + Word16 lshift; + Word64 temp_64, real_sum, imag_sum; + /* calculate per-sample phase and magnitude evolution in preceding frame */ + FOR( k = 0; k < iNumCols; k++ ) + { + real_sum = W_mult_32_32( prev_real_fx[k], prev_real_fx[k] ); + rat_real_sum_q = add( shl( exp, 1 ), 1 ); + imag_sum = W_mult_32_32( prev_imag_fx[k], prev_imag_fx[k] ); + rat_imag_sum_q = add( shl( exp, 1 ), 1 ); + temp_64 = W_add( real_sum, imag_sum ); + lshift = W_norm( temp_64 ); + temp_32 = W_extract_h( W_shl( temp_64, lshift ) ); + sqrt_exp = sub( add( shl( exp, 1 ), lshift ), 31 ); + sqrt_exp = sub( 31, sqrt_exp ); + urh_fx[k] = Sqrt32( temp_32, &sqrt_exp ); + urh_exp[k] = sub( 31, sqrt_exp ); + // In Float the condition is if ( urh[k] < EPSILON ) + IF( EQ_32( urh_fx[k], 0 ) ) + { + /* zero encountered */ + BREAK; + } + + uth_fx[k] = L_shl( BASOP_util_atan2( prev_imag_fx[k], prev_real_fx[k], 0 ), 15 ); // Q28 + /* phase unwrap */ + IF( EQ_32( k, 0 ) ) + { + uthu_fx[0] = uth_fx[0]; + } + ELSE + { + /* phase unwrap */ + ph_diff_fx = L_sub( uth_fx[k], uth_fx[k - 1] ); + + uthu_fx[k] = uth_fx[k]; + Word32 quot_fx_durho; + Word16 s = 0, s_diff; + Word32 add_fact, quo_sq; + IF( GE_32( L_abs( ph_diff_fx ), L_shr( PI2_FX, 2 ) ) ) + { + temp_32 = L_deposit_h( BASOP_Util_Divide3232_Scale( ph_diff_fx, PI2_FX, &s ) ); // Q(31) + ph_adj_t_fx = ( temp_32 == ONE_IN_Q30 ) ? L_sub( ONE_IN_Q31, 1 ) : L_shl( temp_32, s ); + IF( EQ_32( L_abs( L_sub( L_add( ph_adj_t_fx, 1 ), L_shr( ph_adj_t_fx, 31 ) ) ), ONE_IN_Q30 ) ) + { + ph_adj_t_fx = L_shr( ph_adj_t_fx, 31 ); + } + add_fact = ( L_abs( ph_adj_t_fx ) >= ONE_IN_Q30 ) ? ( ( ph_adj_t_fx < 0 ) ? 1686629713 : -1686629713 ) : 0; + ph_adj_fx = W_add( add_fact, ph_adj_fx ); // Q28 + } + /* unwrapped phase in uthu */ + uthu_fx[k] = W_add( uthu_fx[k], ph_adj_fx ); // Q28 + /* mean and stdev of per-sample magnitude ratios */ + s_diff = sub( urh_exp[k - 1], urh_exp[k] ); + temp_16 = BASOP_Util_Divide3232_Scale( urh_fx[k], urh_fx[k - 1], &s ); + quot_fx = L_shl( temp_16, 16 ); // Q(31-s) + quot_exp[k] = sub( sub( 31, s_diff ), s ); + quot_fx_durho = quot_fx; + drho_exp[k] = quot_exp[k]; + IF( GE_32( k, 2 ) ) + { + IF( LT_16( drho_exp[k - 1], drho_exp[k] ) ) + { + quot_fx_durho = L_shr( quot_fx_durho, sub( drho_exp[k], drho_exp[k - 1] ) ); + drho_exp[k] = drho_exp[k - 1]; + } + ELSE IF( GT_16( drho_exp[k - 1], drho_exp[k] ) ) + { + drho_fx = W_shr( drho_fx, sub( drho_exp[k - 1], drho_exp[k] ) ); + } + } + drho_fx = W_add( quot_fx_durho, drho_fx ); // Q(31-s) + srho_exp[k] = sub( 31, shl( add( s_diff, s ), 1 ) ); + quo_sq = Mpy_32_32( quot_fx, quot_fx ); + IF( GE_32( k, 2 ) ) + { + IF( LT_16( srho_exp[k - 1], srho_exp[k] ) ) + { + quo_sq = L_shr( quo_sq, sub( srho_exp[k], srho_exp[k - 1] ) ); + srho_exp[k] = srho_exp[k - 1]; + } + ELSE IF( GT_16( srho_exp[k - 1], srho_exp[k] ) ) + { + srho_fx = W_shr( srho_fx, sub( srho_exp[k - 1], srho_exp[k] ) ); + } + } + srho_fx = W_add( srho_fx, quo_sq ); // Q(31-s) + diff_fx = W_sub( uthu_fx[k], uthu_fx[k - 1] ); // Q28 /* the mean value calculation could be optimized */ + + dth_fx = W_add( dth_fx, diff_fx ); // Q28 + temp_32 = W_extract_l( diff_fx ); + sth_fx = W_add( sth_fx, (Word64) Mpy_32_32( temp_32, temp_32 ) ); // Q25 + + /* mean and stdev of per-sample phase differences */ + } + } + + Word16 tmp_e, tmp, drho_sqr_q, temp_q; + Word32 divide_fact, drho_32, drho_sqr, dth_sqr; + IF( EQ_32( k, iNumCols ) ) + { + + tmp = BASOP_Util_Divide1616_Scale( 1, sub( iNumCols, 1 ), &tmp_e ); + divide_fact = L_shl( tmp, sub( 31, add( 15, negate( tmp_e ) ) ) ); // Q31 + /* mean and stdev of per-sample magnitude ratios */ + lshift = W_norm( drho_fx ); + tmp_e = drho_exp[k - 1]; + IF( LT_16( lshift, 32 ) ) + { + drho_fx = W_shl( drho_fx, lshift ); + tmp_e = add( tmp_e, lshift ); + } + drho_32 = W_extract_h( drho_fx ); // Qtmp_e-32 + drho_32 = Mpy_32_32( drho_32, divide_fact ); + drho_sqr = Mpy_32_32( drho_32, drho_32 ); // Q(2*(tmp_e -32) - 31) + temp_64 = W_mult_32_32( sub( iNumCols, 1 ), drho_sqr ); // Q(2*(tmp_e -32) - 30) + drho_sqr_q = sub( shl( sub( tmp_e, 32 ), 1 ), 30 ); + temp_q = srho_exp[k - 1]; + IF( GT_16( srho_exp[k - 1], drho_sqr_q ) ) + { + temp_64 = W_shl( temp_64, sub( srho_exp[k - 1], drho_sqr_q ) ); + temp_q = srho_exp[k - 1]; + } + ELSE IF( GT_16( drho_sqr_q, srho_exp[k - 1] ) ) + { + srho_fx = W_shl( srho_fx, sub( drho_sqr_q, srho_exp[k - 1] ) ); + temp_q = drho_sqr_q; + } + temp_64 = W_sub( srho_fx, temp_64 ); + drho_q = sub( tmp_e, 32 ); + IF( GT_64( temp_64, 0 ) ) + { + lshift = W_norm( temp_64 ); + temp_32 = W_extract_h( W_shl( temp_64, lshift ) ); + sqrt_exp = sub( add( temp_q, lshift ), 32 ); + tmp = BASOP_Util_Divide1616_Scale( 1, sub( iNumCols, 2 ), &tmp_e ); + divide_fact = L_shl( tmp, sub( 31, add( 15, negate( tmp_e ) ) ) ); // Q31 + temp_32 = Mpy_32_32( temp_32, divide_fact ); // Qsqrt_exp + sqrt_exp1 = sub( 31, sqrt_exp ); + srho_fx = Sqrt32( temp_32, &sqrt_exp1 ); + srho_q = sub( 31, sqrt_exp1 ); + } + ELSE + { + srho_q = 31; + srho_fx = 0; + } + /* mean and stdev of per-sample phase differences */ + tmp = BASOP_Util_Divide1616_Scale( 1, sub( iNumCols, 1 ), &tmp_e ); + divide_fact = L_shl( tmp, sub( 31, add( 15, negate( tmp_e ) ) ) ); // Q31 + /* mean and stdev of per-sample phase differences */ + lshift = W_norm( dth_fx ); + dth_fx = W_shl( dth_fx, lshift ); // Q28+lshift + dth32 = W_extract_h( dth_fx ); // Q28+lshift-32 + dth_q = sub( add( 28, lshift ), 32 ); + dth32 = Mpy_32_32( dth32, divide_fact ); + dth_sqr = Mpy_32_32( dth32, dth32 ); // Q28+lshift-32 + temp_64 = W_mult_32_32( sub( iNumCols, 1 ), dth_sqr ); // Q(2*lshift-39) + temp_q = sub( sub( shl( lshift, 1 ), 8 ), 30 ); + // printf( "%f \t", temp ); + IF( GT_16( temp_q, 25 ) ) + { + + sth_fx = W_shl( sth_fx, sub( temp_q, 25 ) ); + } + ELSE IF( GT_16( 25, temp_q ) ) + { + temp_64 = W_shl( temp_64, sub( 25, temp_q ) ); + temp_q = 25; + } + + temp_64 = W_sub( sth_fx, temp_64 ); + IF( GT_64( temp_64, 0 ) ) + { + lshift = W_norm( temp_64 ); + temp_32 = W_extract_h( W_shl( temp_64, lshift ) ); + sqrt_exp = sub( add( temp_q, lshift ), 32 ); + tmp = BASOP_Util_Divide1616_Scale( 1, sub( iNumCols, 2 ), &tmp_e ); + divide_fact = L_shl( tmp, sub( 31, add( 15, negate( tmp_e ) ) ) ); // Q31 + temp_32 = Mpy_32_32( temp_32, divide_fact ); // Qsqrt_exp + sqrt_exp1 = sub( 31, sqrt_exp ); + sth_fx = Sqrt32( temp_32, &sqrt_exp1 ); + sth_q = sub( 31, sqrt_exp1 ); + } + ELSE + { + sth_fx = 0; + sth_q = 31; + } + + /* do phase extension only IF the std deviations are small */ + IF( LT_64( srho_fx, W_shl( SRHO_THRESH_FX, sub( srho_q, 31 ) ) ) || LT_64( sth_fx, W_shl( STH_THRESH_FX, sub( sth_q, 31 ) ) ) ) + { + dth32 = L_shl( Mpy_32_32( dth32, PI_CONST ), sub( 31, dth_q ) ); // Q28+lshift-32-16 + dth16 = extract_h( dth32 ); + fac_ph_real_fx = L_deposit_h( getCosWord16R2( dth16 ) ); + fac_ph_imag_fx = L_deposit_h( getSineWord16R2( dth16 ) ); + ///* calculate complex evolution factor */ + fac_real_fx = Mpy_32_32( min( L_shl( 1, drho_q ), drho_32 ), fac_ph_real_fx ); // Qdrho_exp + fac_imag_fx = Mpy_32_32( min( L_shl( 1, drho_q ), drho_32 ), fac_ph_imag_fx ); // Qdrho_exp +#if START_VAL_AVG_LEN > 1 + /* Calculate start value FOR evolution from last samples of previous frame */ + fac_powj_real_fx = fac_real_fx; + fac_powj_imag_fx = fac_imag_fx; + start_real_fx = prev_real_fx[iNumCols - 1]; + start_imag_fx = prev_imag_fx[iNumCols - 1]; + FOR( j = 1; j < START_VAL_AVG_LEN; j++ ) + { + start_real_fx = L_add( L_shr( start_real_fx, sub( exp, sub( add( drho_q, exp ), 31 ) ) ), L_sub( Mpy_32_32( fac_powj_real_fx, prev_real_fx[iNumCols - j - 1] ), Mpy_32_32( fac_powj_imag_fx, prev_imag_fx[iNumCols - j - 1] ) ) ); // Q(drho_q+exp-31) + start_imag_fx = L_add( L_shr( start_imag_fx, sub( exp, sub( add( drho_q, exp ), 31 ) ) ), L_add( Mpy_32_32( fac_powj_imag_fx, prev_real_fx[iNumCols - j - 1] ), Mpy_32_32( fac_powj_real_fx, prev_imag_fx[iNumCols - j - 1] ) ) ); // Q(drho_q+exp-31) + temp_fx = L_shl( L_sub( Mpy_32_32( fac_powj_real_fx, fac_real_fx ), Mpy_32_32( fac_powj_imag_fx, fac_imag_fx ) ), sub( sub( drho_q, shl( drho_q, 1 ) ), 31 ) ); // Qdrho_q + fac_powj_imag_fx = L_shl( L_add( Mpy_32_32( fac_powj_imag_fx, fac_real_fx ), Mpy_32_32( fac_powj_real_fx, fac_imag_fx ) ), sub( sub( drho_q, shl( drho_q, 1 ) ), 31 ) ); // Qdrho_q + fac_powj_real_fx = temp_fx; + } + start_q = sub( add( drho_q, exp ), 30 ); +#else + /* take last sample of previous frame as start value */ + start_real = prev_real[iNumCols - 1]; + start_imag = prev_imag[iNumCols - 1]; +#endif + +#if DO_PERTURB != 0 + + /* make evolution less static: apply per samples differences as in preceding frame */ + rat_real_fx = W_add( W_mult_32_32( prev_real_fx[1], prev_real_fx[0] ), W_mult_32_32( prev_imag_fx[1], prev_imag_fx[0] ) ); // 2*exp + rat_imag_fx = W_add( W_mult_32_32( -prev_real_fx[1], prev_imag_fx[0] ), W_mult_32_32( prev_imag_fx[1], prev_real_fx[0] ) ); // 2*exp + +#if PH_PERT_ONLY != 0 + + lshift = W_norm( rat_real_fx ); + temp_64 = W_shl( rat_real_fx, lshift ); // Q2*exp+lshift + rat_real32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_real_q = sub( add( shl( exp, 1 ), lshift ), 31 ); + lshift = W_norm( rat_imag_fx ); + temp_64 = W_shl( rat_imag_fx, lshift ); // Q2*exp+lshift + rat_imag32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_imag_q = sub( add( shl( exp, 1 ), lshift ), 31 ); + real_sum = W_mult_32_32( rat_real32_fx, rat_real32_fx ); + rat_real_sum_q = add( shl( rat_real_q, 1 ), 1 ); + imag_sum = W_mult_32_32( rat_imag32_fx, rat_imag32_fx ); + rat_imag_sum_q = add( shl( rat_imag_q, 1 ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_add( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + temp_32 = W_extract_h( temp_64 ); + sqrt_exp = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + /* only phase perturbation */ + sqrt_exp = sub( 31, sqrt_exp ); + tmp_e = 0; + abs_temp_fx = Sqrt32( temp_32, &sqrt_exp ); // Q(31-sqrt_exp) + + lshift = norm_l( drho_32 ); + drho_32 = L_shl( drho_32, lshift ); + drho_q = add( drho_q, lshift ); + IF( EQ_16( drho_q, 31 ) ) + { + abs2inv_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( L_min( ONE_IN_Q31, drho_32 ), L_max( 1, abs_temp_fx ), &tmp_e ) ); // +drho_q +sqrt_exp-tmp_e + } + ELSE + { + abs2inv_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( L_min( L_shl( 1, drho_q ), drho_32 ), L_max( 1, abs_temp_fx ), &tmp_e ) ); // +drho_q +sqrt_exp-tmp_e + } + temp_16 = sub( add( drho_q, sqrt_exp ), tmp_e ); + + rat_real_fx = W_mult_32_32( rat_real32_fx, abs2inv_fx ); + + rat_imag_fx = W_mult_32_32( rat_imag32_fx, abs2inv_fx ); + rat_real_q = add( add( rat_real_q, temp_16 ), 1 ); + + rat_imag_q = add( add( rat_imag_q, temp_16 ), 1 ); + +#else + /* phase and magnitude perturbation */ + abs2inv = 1 / ( max( 1, drho ) * ( SQR( prev_real[0] ) + SQR( prev_imag[0] ) ) ); + rat_real *= abs2inv; + rat_imag *= abs2inv; +#endif + lshift = W_norm( rat_real_fx ); + temp_64 = W_shl( rat_real_fx, lshift ); // Q2*exp+lshift + rat_real32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_real_q = sub( add( rat_real_q, lshift ), 32 ); + lshift = W_norm( rat_imag_fx ); + temp_64 = W_shl( rat_imag_fx, lshift ); // Q2*exp+lshift + rat_imag32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_imag_q = sub( add( rat_imag_q, lshift ), 32 ); + + /* apply complex evolution FOR first substitution sample */ + + real_sum = W_mult_32_32( rat_real32_fx, start_real_fx ); + rat_real_sum_q = add( add( rat_real_q, start_q ), 1 ); + imag_sum = W_mult_32_32( rat_imag32_fx, start_imag_fx ); + rat_imag_sum_q = add( add( rat_imag_q, start_q ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_sub( real_sum, imag_sum ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + rec_real_fx[0] = W_extract_h( temp_64 ); // sqrt_exp + lshift-32 + rec_real_exp[0] = sub( add( sqrt_exp, lshift ), 32 ); + + real_sum = W_mult_32_32( rat_imag32_fx, start_real_fx ); + rat_real_sum_q = add( add( rat_imag_q, start_q ), 1 ); + imag_sum = W_mult_32_32( rat_real32_fx, start_imag_fx ); + rat_imag_sum_q = add( add( rat_real_q, start_q ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_add( real_sum, imag_sum ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + rec_imag_fx[0] = W_extract_h( temp_64 ); // sqrt_exp + lshift-32 + rec_imag_exp[0] = sub( add( sqrt_exp, lshift ), 32 ); + FOR( j = 2; j < iNumCols; j++ ) + { + rat_real_fx = W_add( W_mult_32_32( prev_real_fx[j], prev_real_fx[j - 1] ), W_mult_32_32( prev_imag_fx[j], prev_imag_fx[j - 1] ) ); // 2*exp + rat_imag_fx = W_add( W_mult_32_32( -prev_real_fx[j], prev_imag_fx[j - 1] ), W_mult_32_32( prev_imag_fx[j], prev_real_fx[j - 1] ) ); // 2*exp +#if PH_PERT_ONLY != 0 + lshift = W_norm( rat_real_fx ); + temp_64 = W_shl( rat_real_fx, lshift ); // Q2*exp+lshift + rat_real32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_real_q = sub( add( shl( exp, 1 ), lshift ), 31 ); + lshift = W_norm( rat_imag_fx ); + temp_64 = W_shl( rat_imag_fx, lshift ); // Q2*exp+lshift + rat_imag32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_imag_q = sub( add( shl( exp, 1 ), lshift ), 31 ); + real_sum = W_mult_32_32( rat_real32_fx, rat_real32_fx ); + rat_real_sum_q = add( shl( rat_real_q, 1 ), 1 ); + imag_sum = W_mult_32_32( rat_imag32_fx, rat_imag32_fx ); + rat_imag_sum_q = add( shl( rat_imag_q, 1 ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + + temp_64 = W_add( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + temp_32 = W_extract_h( temp_64 ); + sqrt_exp = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + /* only phase perturbation */ + sqrt_exp = sub( 31, sqrt_exp ); + tmp_e = 0; + abs_temp_fx = Sqrt32( temp_32, &sqrt_exp ); // Q(31-sqrt_exp) + + IF( EQ_16( drho_q, 31 ) ) + { + abs2inv_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( min( ONE_IN_Q31, drho_32 ), max( 1, abs_temp_fx ), &tmp_e ) ); // +drho_q +sqrt_exp-tmp_e + } + ELSE + { + abs2inv_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( min( L_shl( 1, drho_q ), drho_32 ), max( 1, abs_temp_fx ), &tmp_e ) ); // +drho_q +sqrt_exp-tmp_e + } + temp_16 = sub( add( drho_q, sqrt_exp ), tmp_e ); + + rat_real_fx = W_mult_32_32( rat_real32_fx, abs2inv_fx ); + rat_imag_fx = W_mult_32_32( rat_imag32_fx, abs2inv_fx ); + rat_real_q = add( add( rat_real_q, temp_16 ), 1 ); + rat_imag_q = add( add( rat_imag_q, temp_16 ), 1 ); + +#else + /* phase and magnitude perturbation */ + abs2inv = 1 / ( max( 1, drho ) * ( SQR( prev_real[j - 1] ) + SQR( prev_imag[j - 1] ) ) ); +#endif + + lshift = W_norm( rat_real_fx ); + temp_64 = W_shl( rat_real_fx, lshift ); // Q2*exp+lshift + rat_real32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_real_q = sub( add( rat_real_q, lshift ), 32 ); + lshift = W_norm( rat_imag_fx ); + temp_64 = W_shl( rat_imag_fx, lshift ); // Q2*exp+lshift + rat_imag32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_imag_q = sub( add( rat_imag_q, lshift ), 32 ); + + + real_sum = W_mult_32_32( rat_real32_fx, rec_real_fx[j - 2] ); + rat_real_sum_q = add( add( rat_real_q, rec_real_exp[j - 2] ), 1 ); + imag_sum = W_mult_32_32( rat_imag32_fx, rec_imag_fx[j - 2] ); + rat_imag_sum_q = add( add( rat_imag_q, rec_imag_exp[j - 2] ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_sub( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + rec_real_fx[j - 1] = W_extract_h( temp_64 ); // sqrt_exp + lshift-32 + rec_real_exp[j - 1] = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + + real_sum = W_mult_32_32( rat_imag32_fx, rec_real_fx[j - 2] ); + rat_real_sum_q = add( add( rat_imag_q, rec_real_exp[j - 2] ), 1 ); + imag_sum = W_mult_32_32( rat_real32_fx, rec_imag_fx[j - 2] ); + rat_imag_sum_q = add( add( rat_real_q, rec_imag_exp[j - 2] ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_add( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + rec_imag_fx[j - 1] = W_extract_h( temp_64 ); // sqrt_exp + lshift-32 + rec_imag_exp[j - 1] = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + } + + /* do the same FOR samples of crossfade region */ + FOR( j = 1; j < CLDFB_PLC_XF + 2; j++ ) + { + rat_real_fx = W_add( W_mult_32_32( prev_real_fx[j], prev_real_fx[j - 1] ), W_mult_32_32( prev_imag_fx[j], prev_imag_fx[j - 1] ) ); // 2*exp + rat_imag_fx = W_add( W_mult_32_32( -prev_real_fx[j], prev_imag_fx[j - 1] ), W_mult_32_32( prev_imag_fx[j], prev_real_fx[j - 1] ) ); // 2*exp + +#if PH_PERT_ONLY != 0 + + lshift = W_norm( rat_real_fx ); + temp_64 = W_shl( rat_real_fx, lshift ); // Q2*exp+lshift + rat_real32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_real_q = sub( add( shl( exp, 1 ), lshift ), 31 ); + lshift = W_norm( rat_imag_fx ); + temp_64 = W_shl( rat_imag_fx, lshift ); // Q2*exp+lshift + rat_imag32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_imag_q = sub( add( shl( exp, 1 ), lshift ), 31 ); + real_sum = W_mult_32_32( rat_real32_fx, rat_real32_fx ); + rat_real_sum_q = add( shl( rat_real_q, 1 ), 1 ); + imag_sum = W_mult_32_32( rat_imag32_fx, rat_imag32_fx ); + rat_imag_sum_q = add( shl( rat_imag_q, 1 ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_add( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + temp_32 = W_extract_h( temp_64 ); + sqrt_exp = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + /* only phase perturbation */ + sqrt_exp = sub( 31, sqrt_exp ); + tmp_e = 0; + abs_temp_fx = Sqrt32( temp_32, &sqrt_exp ); // Q(31-sqrt_exp) + + IF( EQ_16( drho_q, 31 ) ) + { + abs2inv_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( min( ONE_IN_Q31, drho_32 ), max( 1, abs_temp_fx ), &tmp_e ) ); // +drho_q +sqrt_exp-tmp_e + } + ELSE + { + abs2inv_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( min( L_shl( 1, drho_q ), drho_32 ), max( 1, abs_temp_fx ), &tmp_e ) ); // +drho_q +sqrt_exp-tmp_e + } + temp_16 = sub( add( drho_q, sqrt_exp ), tmp_e ); + rat_real_fx = W_mult_32_32( rat_real32_fx, abs2inv_fx ); + rat_imag_fx = W_mult_32_32( rat_imag32_fx, abs2inv_fx ); + rat_real_q = add( add( rat_real_q, temp_16 ), 1 ); + rat_imag_q = add( add( rat_imag_q, temp_16 ), 1 ); +#else + abs2inv = 1 / ( max( 1, drho ) * ( SQR( prev_real[j - 1] ) + SQR( prev_imag[j - 1] ) ) ); +#endif + lshift = W_norm( rat_real_fx ); + temp_64 = W_shl( rat_real_fx, lshift ); // Q2*exp+lshift + rat_real32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_real_q = sub( add( rat_real_q, lshift ), 32 ); + lshift = W_norm( rat_imag_fx ); + temp_64 = W_shl( rat_imag_fx, lshift ); // Q2*exp+lshift + rat_imag32_fx = W_extract_h( temp_64 ); // Q2*exp+lshift-31 + rat_imag_q = sub( add( rat_imag_q, lshift ), 32 ); + + + real_sum = W_mult_32_32( rat_real32_fx, rec_real_fx[j + iNumCols - 3] ); + rat_real_sum_q = add( add( rat_real_q, rec_real_exp[j + iNumCols - 3] ), 1 ); + imag_sum = W_mult_32_32( rat_imag32_fx, rec_imag_fx[j + iNumCols - 3] ); + rat_imag_sum_q = add( add( rat_imag_q, rec_imag_exp[j + iNumCols - 3] ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_sub( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + rec_real_fx[j + iNumCols - 2] = W_extract_h( temp_64 ); // sqrt_exp + lshift-32 + rec_real_exp[j + iNumCols - 2] = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + + real_sum = W_mult_32_32( rat_imag32_fx, rec_real_fx[j + iNumCols - 3] ); + rat_real_sum_q = add( add( rat_imag_q, rec_real_exp[j + iNumCols - 3] ), 1 ); + imag_sum = W_mult_32_32( rat_real32_fx, rec_imag_fx[j + iNumCols - 3] ); + rat_imag_sum_q = add( add( rat_real_q, rec_imag_exp[j + iNumCols - 3] ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + temp_64 = W_add( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( temp_64 ); + temp_64 = W_shl( temp_64, lshift ); + rec_imag_fx[j + iNumCols - 2] = W_extract_h( temp_64 ); // sqrt_exp + lshift-32 + rec_imag_exp[j + iNumCols - 2] = sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ); + } +#else + rec_real[0] = fac_real * start_real - fac_imag * start_imag; + rec_imag[0] = fac_imag * start_real + fac_real * start_imag; + FOR( j = 1; j < iNumCols + CLDFB_PLC_XF; j++ ) + { + rec_real[j] = fac_real * rec_real[j - 1] - fac_imag * rec_imag[j - 1]; + rec_imag[j] = fac_imag * rec_real[j - 1] + fac_real * rec_imag[j - 1]; + } +#endif + +#if CLDFB_PLC_XF > 0 + /* apply crossfade */ + FOR( j = 0; j < CLDFB_PLC_XF; j++ ) + { + rec_real_fx[iNumCols + j] = Mpy_32_32( xf_alp_fx[j], rec_real_fx[iNumCols + j] ); + rec_imag_fx[iNumCols + j] = Mpy_32_32( xf_alp_fx[j], rec_imag_fx[iNumCols + j] ); + xf_bet_fx[j] = L_sub( ONE_IN_Q31, xf_alp_fx[j] ); + } +#endif + } + ELSE + { + Word16 guard_bits = find_guarded_bits_fx( iNumCols ); + /* do complex lpc combined with frame repetition */ + Ruu_real_fx[0] = W_add( W_shr( W_mult_32_32( prev_real_fx[0], prev_real_fx[0] ), guard_bits ), W_shr( W_mult_32_32( prev_imag_fx[0], prev_imag_fx[0] ), guard_bits ) ); + Ruu_real_fx[1] = 0; + Ruu_imag_fx[1] = 0; + FOR( j = 1; j < iNumCols; j++ ) + { + Ruu_real_fx[0] = W_add( Ruu_real_fx[0], W_add( W_shr( W_mult_32_32( prev_real_fx[j], prev_real_fx[j] ), guard_bits ), W_shr( W_mult_32_32( prev_imag_fx[j], prev_imag_fx[j] ), guard_bits ) ) ); + Ruu_real_fx[1] = W_add( Ruu_real_fx[1], W_add( W_shr( W_mult_32_32( prev_real_fx[j], prev_real_fx[j - 1] ), guard_bits ), W_shr( W_mult_32_32( prev_imag_fx[j], prev_imag_fx[j - 1] ), guard_bits ) ) ); + Ruu_imag_fx[1] = W_add( Ruu_imag_fx[1], W_sub( W_shr( W_mult_32_32( prev_imag_fx[j], prev_real_fx[j - 1] ), guard_bits ), W_shr( W_mult_32_32( prev_real_fx[j], prev_imag_fx[j - 1] ), guard_bits ) ) ); + } + // printf( "%.7f \t", Ruu_real[1] + lshift = W_norm( Ruu_real_fx[0] ); + Ruu_real_fx_0 = W_extract_h( W_shl( Ruu_real_fx[0], lshift ) ); + Ruu_real_fx_0_q = sub( add( sub( add( shl( exp, 1 ), 1 ), guard_bits ), lshift ), 32 ); + lshift = W_norm( Ruu_real_fx[0] ); + Ruu_real_fx_1 = W_extract_h( W_shl( Ruu_real_fx[1], lshift ) ); + Ruu_real_fx_1_q = sub( add( sub( add( shl( exp, 1 ), 1 ), guard_bits ), lshift ), 32 ); + lshift = W_norm( Ruu_real_fx[0] ); + Ruu_imag_fx_1 = W_extract_h( W_shl( Ruu_imag_fx[1], lshift ) ); + Ruu_imag_fx_1_q = sub( add( sub( add( shl( exp, 1 ), 1 ), guard_bits ), lshift ), 32 ); + IF( GT_64( Ruu_real_fx[0], 0 ) ) + { + /* prediction coefficient */ + fac_real_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( Ruu_real_fx_1, Ruu_real_fx_0, &tmp_e ) ); + fac_real_q = sub( add( sub( 31, tmp_e ), Ruu_real_fx_1_q ), Ruu_real_fx_0_q ); + fac_imag_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( Ruu_imag_fx_1, Ruu_real_fx_0, &tmp_e ) ); + fac_imag_q = sub( add( sub( 31, tmp_e ), Ruu_imag_fx_1_q ), Ruu_real_fx_0_q ); + } + ELSE + { + fac_imag_fx = 0; + fac_imag_q = 31; + fac_real_fx = 0; + fac_real_q = 31; + } + + /* apply prediction using last sample of preceding frame as start value and combine with previous frame samples */ + fac_powj_real_fx = fac_real_fx; + fac_powj_imag_fx = fac_imag_fx; + + Word16 powj_real_q = fac_real_q; + Word16 powj_imag_q = fac_imag_q; + + real_sum = W_mult_32_32( fac_real_fx, fac_real_fx ); + rat_real_sum_q = add( shl( fac_real_q, 1 ), 1 ); + imag_sum = W_mult_32_32( fac_imag_fx, fac_imag_fx ); + rat_imag_sum_q = add( shl( fac_imag_q, 1 ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + sqrt_exp = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + sqrt_exp = rat_real_sum_q; + } + abs_fac_fx = W_add( W_shr( real_sum, 1 ), W_shr( imag_sum, 1 ) ); + lshift = W_norm( abs_fac_fx ); + abs_fac_32 = W_extract_h( W_shl( abs_fac_fx, lshift ) ); + sqrt_exp = sub( 31, ( sub( add( sub( sqrt_exp, 1 ), lshift ), 32 ) ) ); + abs_fac_32 = Sqrt32( abs_fac_32, &sqrt_exp ); + sqrt_exp = sub( 31, sqrt_exp ); + abs_fac_32 = L_shr( abs_fac_32, sub( sqrt_exp, 31 ) ); // Q31 + sqrt_exp = 31; + abs_fac_powj_32 = L_shr( abs_fac_32, 1 ); // Q30 + sqrt_exp = 30; + + FOR( j = 0; j < iNumCols; j++ ) + { + comp_fac_fx = L_sub( L_shl( 1, sqrt_exp ), abs_fac_powj_32 ); + real_sum = W_mult_32_32( prev_real_fx[iNumCols - 1], fac_powj_real_fx ); + rat_real_sum_q = add( add( exp, powj_real_q ), 1 ); + imag_sum = W_mult_32_32( prev_imag_fx[iNumCols - 1], fac_powj_imag_fx ); + rat_imag_sum_q = add( add( exp, powj_imag_q ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_sub( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + rat_real_sum_q = sub( rat_real_sum_q, guard_bits ); + imag_sum = W_mult_32_32( prev_real_fx[j], comp_fac_fx ); + rat_imag_sum_q = add( add( exp, sqrt_exp ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_add( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + lshift = W_norm( real_sum ); + rec_real_fx[j] = W_extract_h( W_shl( real_sum, lshift ) ); + rec_real_exp[j] = sub( add( sub( rat_real_sum_q, guard_bits ), lshift ), 32 ); + real_sum = W_mult_32_32( prev_real_fx[iNumCols - 1], fac_powj_imag_fx ); + rat_real_sum_q = add( add( exp, powj_imag_q ), 1 ); + imag_sum = W_mult_32_32( prev_imag_fx[iNumCols - 1], fac_powj_real_fx ); + rat_imag_sum_q = add( add( exp, powj_real_q ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_add( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + rat_real_sum_q = sub( rat_real_sum_q, guard_bits ); + imag_sum = W_mult_32_32( prev_imag_fx[j], comp_fac_fx ); + rat_imag_sum_q = add( add( exp, sqrt_exp ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_add( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + + lshift = W_norm( real_sum ); + rec_imag_fx[j] = W_extract_h( W_shl( real_sum, lshift ) ); + rec_imag_exp[j] = sub( add( sub( rat_real_sum_q, guard_bits ), lshift ), 32 ); + + abs_fac_powj_32 = Mpy_32_32( abs_fac_powj_32, abs_fac_32 ); + + + real_sum = W_mult_32_32( fac_powj_real_fx, fac_real_fx ); + rat_real_sum_q = add( add( fac_real_q, powj_real_q ), 1 ); + imag_sum = W_mult_32_32( fac_powj_imag_fx, fac_imag_fx ); + rat_imag_sum_q = add( add( fac_imag_q, powj_imag_q ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_sub( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + // rat_real_sum_q = rat_real_sum_q - 1; + lshift = W_norm( real_sum ); + temp_32 = W_extract_h( W_shl( real_sum, lshift ) ); + temp_16 = sub( add( sub( rat_real_sum_q, guard_bits ), lshift ), 32 ); + + real_sum = W_mult_32_32( fac_powj_real_fx, fac_imag_fx ); + rat_real_sum_q = fac_imag_q + powj_real_q + 1; + imag_sum = W_mult_32_32( fac_powj_imag_fx, fac_real_fx ); + rat_imag_sum_q = fac_real_q + powj_imag_q + 1; + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_add( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + // rat_real_sum_q = rat_real_sum_q - 1; + lshift = W_norm( real_sum ); + fac_powj_imag_fx = W_extract_h( W_shl( real_sum, lshift ) ); + powj_imag_q = sub( add( sub( rat_real_sum_q, guard_bits ), lshift ), 32 ); + + fac_powj_real_fx = temp_32; + powj_real_q = temp_16; + } + + + /* prepare XF to next frame using prediction */ + fac_powj_real_fx = fac_real_fx; + fac_powj_imag_fx = fac_imag_fx; + powj_real_q = fac_real_q; + powj_imag_q = fac_imag_q; + abs_fac_powj_32 = abs_fac_32; // Q30 + sqrt_exp = 31; +#if CLDFB_PLC_XF > 0 + guard_bits = find_guarded_bits_fx( CLDFB_PLC_XF ); + FOR( j = 0; j < CLDFB_PLC_XF; j++ ) + { + + + xf_bet_fx[j] = L_sub( ONE_IN_Q31, abs_fac_powj_32 ); + real_sum = W_mult_32_32( rec_real_fx[iNumCols - 1], fac_powj_real_fx ); + rat_real_sum_q = add( add( rec_real_exp[iNumCols - 1], powj_real_q ), 1 ); + imag_sum = W_mult_32_32( rec_imag_fx[iNumCols - 1], fac_powj_imag_fx ); + rat_imag_sum_q = add( add( rec_imag_exp[iNumCols - 1], powj_imag_q ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_sub( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + rat_real_sum_q = sub( rat_real_sum_q, guard_bits ); + + lshift = W_norm( real_sum ); + rec_real_fx[j + iNumCols] = W_extract_h( W_shl( real_sum, lshift ) ); + rec_real_exp[j + iNumCols] = sub( add( rat_real_sum_q, lshift ), 32 ); + + real_sum = W_mult_32_32( rec_real_fx[iNumCols - 1], fac_powj_imag_fx ); + rat_real_sum_q = add( add( rec_real_exp[iNumCols - 1], powj_imag_q ), 1 ); + imag_sum = W_mult_32_32( rec_imag_fx[iNumCols - 1], fac_powj_real_fx ); + rat_imag_sum_q = add( add( rec_imag_exp[iNumCols - 1], powj_real_q ), 1 ); + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + /*sqrt_exp = rat_real_sum_q;*/ + } + real_sum = W_add( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + rat_real_sum_q = sub( rat_real_sum_q, guard_bits ); + + lshift = W_norm( real_sum ); + rec_imag_fx[j + iNumCols] = W_extract_h( W_shl( real_sum, lshift ) ); + rec_imag_exp[j + iNumCols] = sub( add( rat_real_sum_q, lshift ), 32 ); + + abs_fac_powj_32 = W_extract_h( W_mult_32_32( abs_fac_powj_32, abs_fac_32 ) ); // Q31 + + real_sum = W_mult_32_32( fac_powj_real_fx, fac_real_fx ); + rat_real_sum_q = add( add( fac_real_q, powj_real_q ), 1 ); + imag_sum = W_mult_32_32( fac_powj_imag_fx, fac_imag_fx ); + rat_imag_sum_q = add( add( fac_imag_q, powj_imag_q ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + } + real_sum = W_sub( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + lshift = W_norm( real_sum ); + temp_32 = W_extract_h( W_shl( real_sum, lshift ) ); + temp_16 = sub( add( sub( rat_real_sum_q, guard_bits ), lshift ), 32 ); + + real_sum = W_mult_32_32( fac_powj_real_fx, fac_imag_fx ); + rat_real_sum_q = add( add( fac_imag_q, powj_real_q ), 1 ); + imag_sum = W_mult_32_32( fac_powj_imag_fx, fac_real_fx ); + rat_imag_sum_q = add( add( fac_real_q, powj_imag_q ), 1 ); + + IF( GT_16( rat_real_sum_q, rat_imag_sum_q ) ) + { + real_sum = W_shr( real_sum, sub( rat_real_sum_q, rat_imag_sum_q ) ); + rat_real_sum_q = rat_imag_sum_q; + } + ELSE + { + imag_sum = W_shr( imag_sum, sub( rat_imag_sum_q, rat_real_sum_q ) ); + } + real_sum = W_add( W_shr( real_sum, guard_bits ), W_shr( imag_sum, guard_bits ) ); + lshift = W_norm( real_sum ); + fac_powj_imag_fx = W_extract_h( W_shl( real_sum, lshift ) ); + powj_imag_q = sub( add( sub( rat_real_sum_q, guard_bits ), lshift ), 32 ); + + fac_powj_real_fx = temp_32; + powj_real_q = temp_16; + } +#endif + } + } + ELSE + { + FOR( j = 0; j < iNumCols; j++ ) + { + rec_real_fx[j] = prev_real_fx[j]; + rec_real_exp[j] = exp; + rec_imag_fx[j] = prev_imag_fx[j]; + rec_imag_exp[j] = exp; + } +#if CLDFB_PLC_XF > 0 + FOR( j = 0; j < CLDFB_PLC_XF; j++ ) + { + xf_bet_fx[j] = ONE_IN_Q31; + rec_real_fx[j + iNumCols] = 0; + rec_real_exp[j + iNumCols] = 31; + rec_imag_fx[j + iNumCols] = 0; + rec_imag_exp[j + iNumCols] = 31; + } +#endif + } + return; +} +/*------------------------------------------------------------------------- + * Function isar_splitBinRendPLCOpen() + * + * + *------------------------------------------------------------------------*/ + +ivas_error isar_splitBinRendPLCOpen( + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC, + Word16 iNumSubSets ) +{ + ivas_error error; + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC; + + error = IVAS_ERR_OK; + IF( ( hSplitRendPLC = (ISAR_SPLIT_REND_PLC_HANDLE) malloc( sizeof( SPLIT_REND_PLC_STRUCT ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for bin split renderer PLC Module \n" ) ); + } + + hSplitRendPLC->prev_bfi = 0; + hSplitRendPLC->bf_count = 0; + hSplitRendPLC->iNumSubSets = iNumSubSets; + + set_l( &hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal_fx[0][0][0], 0, 2 * ( CLDFB_NO_COL_MAX + CLDFB_PLC_XF ) * CLDFB_NO_CHANNELS_MAX ); + set_l( &hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag_fx[0][0][0], 0, 2 * ( CLDFB_NO_COL_MAX + CLDFB_PLC_XF ) * CLDFB_NO_CHANNELS_MAX ); + + *phSplitRendPLC = hSplitRendPLC; + + return error; +} + +/*------------------------------------------------------------------------- + * Function isar_splitBinRendPLCClose() + * + * + *------------------------------------------------------------------------*/ + +void isar_splitBinRendPLCClose( + ISAR_SPLIT_REND_PLC_HANDLE *phSplitRendPLC ) +{ + if ( ( *phSplitRendPLC ) != NULL ) + { + free( ( *phSplitRendPLC ) ); + ( *phSplitRendPLC ) = NULL; + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function isar_splitBinRendPLCsaveState() + * + * + *------------------------------------------------------------------------*/ + +void isar_splitBinRendPLCsaveState( + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 num_chs, + const Word16 iNumBlocks, + const Word16 iNumIterations ) +{ + Word16 k, n; + + /* Save Cldfb frame */ + FOR( k = 0; k < ( iNumBlocks * iNumIterations ); k++ ) + { + FOR( n = 0; n < num_chs; n++ ) + { + mvl2l( &Cldfb_RealBuffer_Binaural_fx[n][k][0], &hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal_fx[n][k][0], CLDFB_NO_CHANNELS_MAX ); + mvl2l( &Cldfb_ImagBuffer_Binaural_fx[n][k][0], &hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag_fx[n][k][0], CLDFB_NO_CHANNELS_MAX ); + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function isar_splitBinRendPLC_xf() + * + * Cross-fade of preceding bad frame into good frame + *------------------------------------------------------------------------*/ + +void isar_splitBinRendPLC_xf_fx( + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 num_chs, + const Word16 iNumBlocks, + const Word16 iNumIterations, + Word32 **ppiDecodingFailed, + Word32 **ppiDecodingFailedPrev, + Word16 exp ) +{ + Word16 n, i, k; + /* Indicate that next transition will be from a good frame */ + hSplitRendPLC->prev_bfi = 0; + move16(); + + /* Reset bf conter */ + hSplitRendPLC->bf_count = 0; + move16(); + + /* Do the cross fade */ + FOR( n = 0; n < num_chs; n++ ) + { + FOR( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) + { + Word32 iSubSet = i % hSplitRendPLC->iNumSubSets; + test(); + IF( EQ_32( ppiDecodingFailedPrev[n][iSubSet], 1 ) && EQ_32( ppiDecodingFailed[n][iSubSet], 0 ) ) + { +#if CLDFB_PLC_XF > 0 + FOR( k = 0; k < CLDFB_PLC_XF; k++ ) + { + Word32 L_tmp; + Word64 W_tmp; + Word16 shift; + W_tmp = W_shr( W_mult_32_32( hSplitRendPLC->CldfbPLC_state.xf_bet_fx[n][i][k], Cldfb_RealBuffer_Binaural_fx[n][k][i] ), 1 ); + W_tmp = W_add( W_tmp, W_shl( L_shl_r( hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal_fx[n][k + ( iNumBlocks * iNumIterations )][i], exp - hSplitRendPLC->CldfbPLC_state.Q_Prev_Bin_fx ), 31 ) ); + + shift = W_norm( W_tmp ); + W_tmp = W_shl( W_tmp, shift ); + L_tmp = W_extract_h( W_tmp ); + L_tmp = L_shr( L_tmp, 31 + shift - 32 ); + Cldfb_RealBuffer_Binaural_fx[n][k][i] = L_tmp; + + W_tmp = W_shr( W_mult_32_32( hSplitRendPLC->CldfbPLC_state.xf_bet_fx[n][i][k], Cldfb_ImagBuffer_Binaural_fx[n][k][i] ), 1 ); + W_tmp = W_add( W_tmp, W_shl( L_shl_r( hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag_fx[n][k + ( iNumBlocks * iNumIterations )][i], exp - hSplitRendPLC->CldfbPLC_state.Q_Prev_Bin_fx ), 31 ) ); + + shift = W_norm( W_tmp ); + W_tmp = W_shl( W_tmp, shift ); + L_tmp = W_extract_h( W_tmp ); + L_tmp = L_shr( L_tmp, 31 + shift - 32 ); + Cldfb_ImagBuffer_Binaural_fx[n][k][i] = L_tmp; + } +#endif + } + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function isar_splitBinRendPLC() + * + * Conceal bad frame + *------------------------------------------------------------------------*/ +void isar_splitBinRendPLC( + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC, + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 num_chs, + const Word16 iNumBlocks, + const Word16 iNumIterations, + int32_t **ppiDecodingFailed, + Word16 exp ) +{ + Word32 i, n, k; + Word32 temp_32, fade_fac_fx; + Word16 div_exp = 0, tmp, exp_fade, frac; + Word32 prev_real_fx[CLDFB_NO_COL_MAX], prev_imag_fx[CLDFB_NO_COL_MAX], rec_real_fx[CLDFB_NO_COL_MAX + CLDFB_PLC_XF], rec_imag_fx[CLDFB_NO_COL_MAX + CLDFB_PLC_XF]; + Word16 rec_real_exp[CLDFB_NO_COL_MAX + CLDFB_PLC_XF], rec_imag_exp[CLDFB_NO_COL_MAX + CLDFB_PLC_XF]; +#if CLDFB_PLC_XF > 0 + Word32 xf_alp_fx[CLDFB_PLC_XF]; +#endif + Word16 iNumCols, fade_start_cntr, mute_cntr, fade_val; + + iNumCols = extract_l( L_mult0( iNumBlocks, iNumIterations ) ); + + /* Indicate that next transition will be from a bad frame */ + hSplitRendPLC->prev_bfi = 1; + + +#if CLDFB_PLC_XF > 0 + FOR( i = 0; i < CLDFB_PLC_XF; i++ ) + { + xf_alp_fx[i] = xf_alp_tab[i]; + } +#endif + Word16 exp1 = exp; + + FOR( n = 0; n < num_chs; n++ ) + { + FOR( i = 0; i < CLDFB_NO_CHANNELS_MAX; i++ ) + { + Word32 iSubSet = i % hSplitRendPLC->iNumSubSets; + FOR( k = 0; k < iNumCols; k++ ) + { + prev_real_fx[k] = L_shl_r( hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal_fx[n][k][i], exp - hSplitRendPLC->CldfbPLC_state.Q_Prev_Bin_fx ); + prev_imag_fx[k] = L_shl_r( hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag_fx[n][k][i], exp - hSplitRendPLC->CldfbPLC_state.Q_Prev_Bin_fx ); + } + adaptive_polar_ext_plc_fx( + prev_real_fx, prev_imag_fx, rec_real_fx, rec_imag_fx, + rec_real_exp, rec_imag_exp +#if CLDFB_PLC_XF > 0 + , + xf_alp_fx, hSplitRendPLC->CldfbPLC_state.xf_bet_fx[n][i], +#endif + exp, + iNumCols ); + + Word16 temp16; + + FOR( k = 0; k < iNumCols; k++ ) + { + temp16 = sub( rec_real_exp[k], exp1 ); + rec_real_fx[k] = L_shr_r_sat( rec_real_fx[k], temp16 ); + rec_real_exp[k] = sub( rec_real_exp[k], temp16 ); + + temp16 = sub( rec_imag_exp[k], exp1 ); + rec_imag_fx[k] = L_shr_r_sat( rec_imag_fx[k], temp16 ); + rec_imag_exp[k] = sub( rec_imag_exp[k], temp16 ); + // Cldfb_RealBuffer_Binaural_fx[n][k][i] = rec_real_fx[k]; + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal_fx[n][k][i] = rec_real_fx[k]; // exp + // Cldfb_ImagBuffer_Binaural_fx[n][k][i] = rec_imag_fx[k] ; + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag_fx[n][k][i] = rec_imag_fx[k]; // exp + if ( ppiDecodingFailed[n][iSubSet] == 1 ) + { /* only then copy to output */ + Cldfb_RealBuffer_Binaural_fx[n][k][i] = rec_real_fx[k]; + Cldfb_ImagBuffer_Binaural_fx[n][k][i] = rec_imag_fx[k]; + } + } + +#if CLDFB_PLC_XF > 0 + FOR( k = iNumCols; k < iNumCols + CLDFB_PLC_XF; k++ ) + { + + temp16 = sub( rec_real_exp[k], exp1 ); + rec_real_fx[k] = L_shr_r_sat( rec_real_fx[k], temp16 ); + rec_real_exp[k] = sub( rec_real_exp[k], temp16 ); + + temp16 = sub( rec_imag_exp[k], exp1 ); + rec_imag_fx[k] = L_shr_r_sat( rec_imag_fx[k], temp16 ); + rec_imag_exp[k] = sub( rec_imag_exp[k], temp16 ); + /*TODO: Will remove the inter conversion later*/ + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinReal_fx[n][k][i] = rec_real_fx[k]; // exp + hSplitRendPLC->CldfbPLC_state.Cldfb_Prev_BinImag_fx[n][k][i] = rec_imag_fx[k]; // exp + } +#endif + } + } + + + /* Check bf counter */ + tmp = BASOP_Util_Divide1616_Scale( PLC_FADE_CNST, iNumCols, &div_exp ); + fade_start_cntr = shr( tmp, ( 15 - div_exp ) ); + tmp = BASOP_Util_Divide1616_Scale( PLC_MUTE_CNST, iNumCols, &div_exp ); + mute_cntr = shr( tmp, ( 15 - div_exp ) ); + + IF( GE_16( hSplitRendPLC->bf_count++, fade_start_cntr ) ) + { + IF( LT_16( hSplitRendPLC->bf_count, mute_cntr ) ) + { + fade_val = extract_l( L_shr( L_mult0( sub( hSplitRendPLC->bf_count, fade_start_cntr ), iNumCols ), 4 ) ); // Q0 + temp_32 = L_mult( -16328, fade_val ); // Q15 + temp_32 = L_shl( temp_32, 1 ); // Q16 + + frac = L_Extract_lc( temp_32, &exp_fade ); /* Extract exponent of temp_32 */ + fade_fac_fx = Pow2( 14, frac ); /* Put 14 as exponent so that */ + exp_fade = 31 - add( sub( exp_fade, 14 ), 16 ); + fade_fac_fx = L_shl( fade_fac_fx, 31 - exp_fade ); // Q31 + + FOR( n = 0; n < num_chs; n++ ) + { + FOR( k = 0; k < iNumCols; k++ ) + { + v_multc_fixed( &Cldfb_RealBuffer_Binaural_fx[n][k][0], fade_fac_fx, &Cldfb_RealBuffer_Binaural_fx[n][k][0], (int16_t) CLDFB_NO_CHANNELS_MAX ); + v_multc_fixed( &Cldfb_ImagBuffer_Binaural_fx[n][k][0], fade_fac_fx, &Cldfb_ImagBuffer_Binaural_fx[n][k][0], (int16_t) CLDFB_NO_CHANNELS_MAX ); + } + } + } + ELSE + { + FOR( n = 0; n < num_chs; n++ ) + { + FOR( k = 0; k < iNumCols; k++ ) + { + set_val_Word32( &Cldfb_RealBuffer_Binaural_fx[n][k][0], 0, (int16_t) CLDFB_NO_CHANNELS_MAX ); + set_val_Word32( &Cldfb_ImagBuffer_Binaural_fx[n][k][0], 0, (int16_t) CLDFB_NO_CHANNELS_MAX ); + } + } + hSplitRendPLC->bf_count = mute_cntr; + } + } + + return; +} +#endif diff --git a/lib_isar/isar_splitRendererPost.c b/lib_isar/isar_splitRendererPost.c new file mode 100644 index 000000000..1bbff0b5c --- /dev/null +++ b/lib_isar/isar_splitRendererPost.c @@ -0,0 +1,2131 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG +#include +#endif +#include "ivas_prot.h" +#include "prot.h" +#include "isar_rom_post_rend.h" +#include "isar_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "prot_fx2.h" +#include "wmc_auto.h" +#include "basop_util.h" +#define Q31_BY_360 ( 5965232 ) // Q31 + + +/*------------------------------------------------------------------------- + * isar_splitBinPostRendOpen() + * + * + *------------------------------------------------------------------------*/ +ivas_error isar_splitBinPostRendOpen( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word32 output_Fs ) +{ + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinRend; + ivas_error error; + Word16 ch; + + IF( ( hBinRend = (ISAR_BIN_HR_SPLIT_POST_REND_HANDLE) malloc( sizeof( ISAR_BIN_HR_SPLIT_POST_REND ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for bin split post renderer Module \n" ) ); + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hBinRend->cldfbSyn[ch] = NULL; + hBinRend->cldfbAna[ch] = NULL; + } +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hBinRend->cldfbSynReconsBinDec[i][ch] = NULL; + } + } +#endif + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + IF( ( error = openCldfb_splitRend( &( hBinRend->cldfbSyn[ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + IF( ( error = openCldfb_splitRend( &( hBinRend->cldfbAna[ch] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + if ( ( error = openCldfb( &( hBinRend->cldfbSynReconsBinDec[i][ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + hBinRend->cf_flag = 0; + set_fix_rotation_mat_fx( hBinRend->fix_pos_rot_mat_fx, pMultiBinPoseData ); + set_pose_types_fx( hBinRend->pose_type, pMultiBinPoseData ); + isar_split_rend_init_huff_cfg( &hBinRend->huff_cfg ); + *hBinHrSplitPostRend = hBinRend; + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * isar_splitBinPostRendClose() + * + * + *------------------------------------------------------------------------*/ + +void isar_splitBinPostRendClose( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE *hBinHrSplitPostRend ) +{ + Word16 ch; + + IF( ( *hBinHrSplitPostRend ) != NULL ) + { + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + IF( ( *hBinHrSplitPostRend )->cldfbSyn[ch] != NULL ) + { + deleteCldfb_splitRend( &( ( *hBinHrSplitPostRend )->cldfbSyn[ch] ) ); + ( *hBinHrSplitPostRend )->cldfbSyn[ch] = NULL; + } + IF( ( *hBinHrSplitPostRend )->cldfbAna[ch] != NULL ) + { + deleteCldfb_splitRend( &( ( *hBinHrSplitPostRend )->cldfbAna[ch] ) ); + ( *hBinHrSplitPostRend )->cldfbAna[ch] = NULL; + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + if ( ( *hBinHrSplitPostRend )->cldfbSynReconsBinDec[i][ch] != NULL ) + { + deleteCldfb( &( ( *hBinHrSplitPostRend )->cldfbSynReconsBinDec[i][ch] ) ); + ( *hBinHrSplitPostRend )->cldfbSynReconsBinDec[i][ch] = NULL; + } + } + } +#endif + + free( ( *hBinHrSplitPostRend ) ); + ( *hBinHrSplitPostRend ) = NULL; + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_split_rend_huffman_decode_opt() + * + * + *-----------------------------------------------------------------------------------------*/ + +static Word16 ivas_split_rend_huffman_decode_opt( + isar_split_rend_huffman_cfg_t *huff_cfg, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word16 *idx_trav_list ) +{ + Word32 i, ind, code, num_bits, code_b, num_bits_read; + const Word32 *codebook; + + codebook = huff_cfg->codebook; + num_bits_read = 0; + move32(); + ind = L_sub( huff_cfg->codebook[0], 1 ); + code = 0; + move32(); + FOR( i = 0; i < huff_cfg->sym_len; i++ ) + { + codebook = codebook + idx_trav_list[i] * 3; + num_bits = codebook[1]; + move32(); + code_b = codebook[2]; + move32(); + num_bits_read = L_sub( num_bits, num_bits_read ); + code = L_shl( code, extract_l( num_bits_read ) ); + IF( GT_32( num_bits_read, 0 ) ) + { + code = L_or( code, ISAR_SPLIT_REND_BITStream_read_int32( pBits, num_bits_read ) ); + } + + IF( EQ_32( code, code_b ) ) + { + ind = codebook[0]; + move32(); + BREAK; + } + + num_bits_read = num_bits; + move32(); + codebook = huff_cfg->codebook; + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + assert( ind >= huff_cfg->codebook[0] ); +#endif + return extract_l( ind ); +} + +/*-----------------------------------------------------------------------------------------* + * Function ivas_split_rend_unquant_md() + * + * + *-----------------------------------------------------------------------------------------*/ + +static void ivas_split_rend_unquant_md_fx( + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd, + ISAR_SPLIT_REND_POSE_TYPE pose_type, + Word16 real_only, + Word32 fix_pos_rot_mat[][BINAURAL_CHANNELS], + const Word32 pred_quant_step ) +{ + Word16 ch1, ch2; + Word16 gd_idx_min; + + test(); + IF( EQ_32( pose_type, PRED_ONLY ) || EQ_32( pose_type, PRED_ROLL_ONLY ) ) + { + Word32 quantstep; + + quantstep = pred_quant_step; + move32(); +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + hMd->pred_mat_re_fx[ch1][ch2] = Mpy_32_16_1( quantstep, extract_l( L_shl( hMd->pred_mat_re_idx[ch1][ch2], Q9 ) ) ); /* Q25 */ + move32(); + hMd->pred_mat_re_fx[ch1][ch2] = L_add( hMd->pred_mat_re_fx[ch1][ch2], L_shr( fix_pos_rot_mat[ch1][ch2], Q6 ) ); /* Q25 */ + move32(); + } + } +#endif + + IF( real_only ) + { +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + hMd->pred_mat_re_fx[ch1][ch2] = Mpy_32_16_1( quantstep, extract_l( L_shl( hMd->pred_mat_re_idx[ch1][ch2], Q9 ) ) ); /* Q25 */ + move32(); + hMd->pred_mat_re_fx[ch1][ch2] = L_add( hMd->pred_mat_re_fx[ch1][ch2], L_shr( ( ch1 == ch2 ) ? ONE_IN_Q31 : 0, Q6 ) ); /* Q25 */ + move32(); + } + } +#endif + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + hMd->pred_mat_im_fx[ch1][ch2] = 0; /* Q25 */ + move32(); + } + } + } + ELSE + { +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + hMd->pred_mat_re_fx[ch1][ch2] = Mpy_32_16_1( quantstep, extract_l( L_shl( hMd->pred_mat_re_idx[ch1][ch2], Q9 ) ) ); /* Q25 */ + move32(); + hMd->pred_mat_re_fx[ch1][ch2] = L_add( hMd->pred_mat_re_fx[ch1][ch2], L_shr( fix_pos_rot_mat[ch1][ch2], Q6 ) ); /* Q25 */ + move32(); + } + } +#endif + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + hMd->pred_mat_im_fx[ch1][ch2] = Mpy_32_16_1( quantstep, extract_l( L_shl( hMd->pred_mat_im_idx[ch1][ch2], Q9 ) ) ); /* Q25 */ + move32(); + } + } + } + } + ELSE IF( EQ_32( pose_type, COM_GAIN_ONLY ) ) + { + gd_idx_min = 0; + move16(); + hMd->gd_idx = add( hMd->gd_idx, gd_idx_min ); + hMd->gd_fx = Mpy_32_16_1( ISAR_SPLIT_REND_D_Q_STEP_Q31, extract_l( L_shl( hMd->gd_idx, Q9 ) ) ); /* Q25 */ + } + ELSE IF( EQ_32( pose_type, LR_GAIN_ONLY ) ) + { + gd_idx_min = 7; + move16(); + hMd->gd_idx = add( hMd->gd_idx, gd_idx_min ); + hMd->gd_fx = Mpy_32_16_1( ISAR_SPLIT_REND_PITCH_G_Q_STEP_Q31, extract_l( L_shl( hMd->gd_idx, Q9 ) ) ); /* Q25 */ + + hMd->gd2_idx = add( hMd->gd2_idx, gd_idx_min ); + hMd->gd2_fx = Mpy_32_16_1( ISAR_SPLIT_REND_PITCH_G_Q_STEP_Q31, extract_l( L_shl( hMd->gd2_idx, Q9 ) ) ); /* Q25 */ + } + ELSE + { + hMd->gd_fx = 0; /* Q25 */ + move32(); + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function isar_splitBinPostRendMdBase2Dec() + * + * + *-----------------------------------------------------------------------------------------*/ + +static void isar_splitBinPostRendMdBase2Dec( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word16 num_subframes, + const Word16 pred_real_bands_yaw, + const Word16 pred_imag_bands_yaw, + const Word16 pred_quant_pnts_yaw, + const Word16 d_bands_yaw, + const Word16 bands_pitch, + const Word16 pred_real_bands_roll, + const Word16 pred_imag_bands_roll ) +{ + Word16 sf_idx, pos_idx, b, ch1, ch2; + Word16 min_pred_idx, min_gd_idx, min_p_gd_idx, pred_code_len, gd_code_len, p_gd_code_len; + Word16 min_pred_roll_idx, pred_roll_code_len; + Word16 pred_cb_idx; + Word16 code; + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd; + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg; + + pHuff_cfg = &hBinHrSplitPostRend->huff_cfg; + + IF( EQ_16( pred_quant_pnts_yaw, ISAR_SPLIT_REND_PRED_63QUANT_PNTS ) ) + { + pred_cb_idx = 1; + move16(); + } + ELSE + { + pred_cb_idx = 0; + move16(); + } + min_pred_idx = extract_l( pHuff_cfg->pred[pred_cb_idx].codebook[0] ); + min_pred_roll_idx = extract_l( pHuff_cfg->pred_roll.codebook[0] ); + min_gd_idx = extract_l( pHuff_cfg->gd.codebook[0] ); + min_p_gd_idx = extract_l( pHuff_cfg->p_gd.codebook[0] ); + pred_code_len = pHuff_cfg->pred_base2_code_len[pred_cb_idx]; + move16(); + pred_roll_code_len = pHuff_cfg->pred_roll_base2_code_len; + move16(); + gd_code_len = pHuff_cfg->gd_base2_code_len; + move16(); + p_gd_code_len = pHuff_cfg->p_gd_base2_code_len; + move16(); + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( pos_idx = 0; pos_idx < sub( pMultiBinPoseData->num_poses, 1 ); pos_idx++ ) + { + IF( EQ_32( hBinHrSplitPostRend->pose_type[pos_idx], ANY_YAW ) ) + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_code_len ) ); + hMd->pred_mat_re_idx[ch1][ch2] = add( code, min_pred_idx ); + move16(); + } + } + } + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_code_len ) ); + hMd->pred_mat_im_idx[ch1][ch2] = add( code, min_pred_idx ); + move16(); + } + } + } +#else + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_code_len ) ); + hMd->pred_mat_re_idx[ch1][ch2] = add( code, min_pred_idx ); + move16(); + } + } + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_code_len ) ); + hMd->pred_mat_im_idx[ch1][ch2] = add( code, min_pred_idx ); + move16(); + } + } + } + FOR( ; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_code_len ) ); + hMd->pred_mat_re_idx[ch1][ch1] = add( code, min_pred_idx ); + move16(); + } + hMd->pred_mat_re_idx[0][1] = 0; + move16(); + hMd->pred_mat_re_idx[1][0] = 0; + move16(); + } +#endif + FOR( b = 0; b < d_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, gd_code_len ) ); + hMd->gd_idx = add( code, min_gd_idx ); + move16(); + } + } + ELSE IF( EQ_32( hBinHrSplitPostRend->pose_type[pos_idx], PITCH_ONLY ) ) + { + FOR( b = 0; b < bands_pitch; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, p_gd_code_len ) ); + hMd->gd_idx = add( code, min_p_gd_idx ); + move16(); + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, p_gd_code_len ) ); + hMd->gd2_idx = add( code, min_p_gd_idx ); + move16(); + } + } + ELSE + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_roll_code_len ) ); + hMd->pred_mat_re_idx[ch1][ch2] = add( code, min_pred_roll_idx ); + move16(); + } + } + } + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_roll_code_len ) ); + hMd->pred_mat_im_idx[ch1][ch2] = add( code, min_pred_roll_idx ); + move16(); + } + } + } +#else + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_roll_code_len ) ); + hMd->pred_mat_re_idx[ch1][ch2] = add( code, min_pred_roll_idx ); + move16(); + } + } + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_roll_code_len ) ); + hMd->pred_mat_im_idx[ch1][ch2] = add( code, min_pred_roll_idx ); + move16(); + } + } + } + FOR( ; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + code = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, pred_roll_code_len ) ); + hMd->pred_mat_re_idx[ch1][ch1] = add( code, min_pred_roll_idx ); + move16(); + } + hMd->pred_mat_re_idx[0][1] = 0; + move16(); + hMd->pred_mat_re_idx[1][0] = 0; + move16(); + } +#endif + } + } + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_splitBinPostRendMdHuffDec() + * + * + *-----------------------------------------------------------------------------------------*/ + +static void ivas_splitBinPostRendMdHuffDec( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word16 num_subframes, + const Word16 pred_real_bands_yaw, + const Word16 pred_imag_bands_yaw, + const Word16 pred_quant_pnts_yaw, + const Word16 d_bands_yaw, + const Word16 bands_pitch, + const Word16 pred_real_bands_roll, + const Word16 pred_imag_bands_roll ) +{ + Word16 pos_idx, b, sf_idx; + Word16 ch1, ch2; + Word16 sym_adj_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 min_pred_idx, max_pred_idx; + Word16 min_pred_roll_idx, max_pred_roll_idx, pred_cb_idx; + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd; + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg; + + pHuff_cfg = &hBinHrSplitPostRend->huff_cfg; + + IF( EQ_16( pred_quant_pnts_yaw, ISAR_SPLIT_REND_PRED_63QUANT_PNTS ) ) + { + pred_cb_idx = 1; + move16(); + } + ELSE + { + pred_cb_idx = 0; + move16(); + } + min_pred_idx = extract_l( pHuff_cfg->pred[pred_cb_idx].codebook[0] ); + max_pred_idx = extract_l( pHuff_cfg->pred[pred_cb_idx].codebook[( pred_quant_pnts_yaw - 1 ) * 3] ); + + min_pred_roll_idx = extract_l( pHuff_cfg->pred_roll.codebook[0] ); + max_pred_roll_idx = extract_l( pHuff_cfg->pred_roll.codebook[( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS - 1 ) * 3] ); + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( pos_idx = 0; pos_idx < sub( pMultiBinPoseData->num_poses, 1 ); pos_idx++ ) + { + IF( EQ_32( hBinHrSplitPostRend->pose_type[pos_idx], ANY_YAW ) ) + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred[pred_cb_idx], pBits, pHuff_cfg->pred_idx_trav[pred_cb_idx] ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_re_idx, 1, min_pred_idx, max_pred_idx ); + } + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred[pred_cb_idx], pBits, pHuff_cfg->pred_idx_trav[pred_cb_idx] ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_im_idx, -1, min_pred_idx, max_pred_idx ); + } +#else + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred[pred_cb_idx], pBits, pHuff_cfg->pred_idx_trav[pred_cb_idx] ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_re_idx, 1, min_pred_idx, max_pred_idx ); + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred[pred_cb_idx], pBits, pHuff_cfg->pred_idx_trav[pred_cb_idx] ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_im_idx, -1, min_pred_idx, max_pred_idx ); + } + FOR( ; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + sym_adj_idx[ch1][ch1] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred[pred_cb_idx], pBits, pHuff_cfg->pred_idx_trav[pred_cb_idx] ); + move16(); + } + sym_adj_idx[1][0] = 0; + move16(); + sym_adj_idx[0][1] = 0; + move16(); + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_re_idx, -1, min_pred_idx, max_pred_idx ); + } +#endif + FOR( b = 0; b < d_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + hMd->gd_idx = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->gd, pBits, pHuff_cfg->gd_idx_trav ); + // hMd->gd_idx = ivas_split_rend_huffman_decode( &pHuff_cfg->gd, pBits ); + } + } + ELSE IF( hBinHrSplitPostRend->pose_type[pos_idx] == PITCH_ONLY ) + { + FOR( b = 0; b < bands_pitch; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + hMd->gd_idx = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->p_gd, pBits, pHuff_cfg->p_gd_idx_trav ); + // hMd->gd_idx = ivas_split_rend_huffman_decode( &pHuff_cfg->gd, pBits ); + + hMd->gd2_idx = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->p_gd, pBits, pHuff_cfg->p_gd_idx_trav ); + } + } + ELSE + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred_roll, pBits, pHuff_cfg->pred_roll_idx_trav ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred_roll, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_re_idx, 1, min_pred_roll_idx, max_pred_roll_idx ); + } + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred_roll, pBits, pHuff_cfg->pred_roll_idx_trav ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred_roll, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_im_idx, -1, min_pred_roll_idx, max_pred_roll_idx ); + } +#else + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred_roll, pBits, pHuff_cfg->pred_roll_idx_trav ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred_roll, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_re_idx, 1, min_pred_roll_idx, max_pred_roll_idx ); + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred_roll, pBits, pHuff_cfg->pred_roll_idx_trav ); + move16(); + // sym_adj_idx[ch1][ch2] = ivas_split_rend_huffman_decode( &pHuff_cfg->pred_roll, pBits ); + } + } + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_im_idx, -1, min_pred_roll_idx, max_pred_roll_idx ); + } + FOR( ; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + sym_adj_idx[ch1][ch1] = ivas_split_rend_huffman_decode_opt( &pHuff_cfg->pred_roll, pBits, pHuff_cfg->pred_roll_idx_trav ); + move16(); + } + sym_adj_idx[1][0] = 0; + move16(); + sym_adj_idx[0][1] = 0; + move16(); + isar_SplitRenderer_getdiagdiff( sym_adj_idx, hMd->pred_mat_re_idx, -1, min_pred_roll_idx, max_pred_roll_idx ); + } +#endif + } + } + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function isar_splitBinPostRendMdDec() + * + * + *-----------------------------------------------------------------------------------------*/ + +void isar_splitBinPostRendMdDec_fx( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + , + BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend +#endif +) +{ + Word16 pos_idx, b, sf_idx, num_subframes, ch1; + Word16 pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word16 pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word16 d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word16 num_quant_strats; +#else + Word16 num_complex_bands, num_quant_strats; +#endif + Word32 quant_strat_bits, is_huff_coding, quant_strat; + Word16 pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word32 pred_1byquantstep_yaw_fx[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; // Q26 + Word32 pred_quantstep_yaw_fx[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; // Q31 +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + Word16 ch1, ch2; +#endif + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd; + ISAR_SPLIT_REND_CONFIG_DATA split_rend_config; + ISAR_SPLIT_REND_ROT_AXIS rot_axis; +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word16 ro_md_flag, num_bits, axis_code; +#endif + + hBinHrSplitPostRend->low_Res = 1; + move16(); + + split_rend_config.dof = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_DOF_BITS ) ); + split_rend_config.hq_mode = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_HQ_MODE_BITS ) ); + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + num_bits = isar_renderSplitGetRot_axisNumBits( split_rend_config.dof ); + if ( num_bits > 0 ) + { + axis_code = (int16_t) ISAR_SPLIT_REND_BITStream_read_int32( pBits, (int32_t) num_bits ); + } + else + { + axis_code = 0; + } + rot_axis = isar_renderSplitGetRot_axisFromCode( split_rend_config.dof, axis_code ); + ro_md_flag = (int16_t) ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_RO_FLAG_BITS ); +#else + rot_axis = (ISAR_SPLIT_REND_ROT_AXIS) ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_ROT_AXIS_BITS ); +#endif + isar_renderSplitGetMultiBinPoseData_fx( &split_rend_config, pMultiBinPoseData, rot_axis ); + + set_fix_rotation_mat_fx( hBinHrSplitPostRend->fix_pos_rot_mat_fx, pMultiBinPoseData ); + set_pose_types_fx( hBinHrSplitPostRend->pose_type, pMultiBinPoseData ); + + num_subframes = EQ_16( hBinHrSplitPostRend->low_Res, 0 ) ? MAX_PARAM_SPATIAL_SUBFRAMES : 1; + move16(); + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + Word16 angle; + + hBinHrSplitPostRend->QuaternionsPre[sf_idx].w_fx = -12582912; /* -3.0f in Q22 */ + move32(); + + angle = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_HEAD_POSE_BITS ) ); + angle = sub( angle, 180 ); + hBinHrSplitPostRend->QuaternionsPre[sf_idx].x_fx = L_shl( angle, Q22 ); /* Q22 */ + move32(); + + angle = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_HEAD_POSE_BITS ) ); + angle = sub( angle, 180 ); + hBinHrSplitPostRend->QuaternionsPre[sf_idx].y_fx = L_shl( angle, Q22 ); /* Q22 */ + move32(); + + angle = extract_l( ISAR_SPLIT_REND_BITStream_read_int32( pBits, ISAR_SPLIT_REND_HEAD_POSE_BITS ) ); + angle = sub( angle, 180 ); + hBinHrSplitPostRend->QuaternionsPre[sf_idx].z_fx = L_shl( angle, Q22 ); /* Q22 */ + move32(); + } + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + isar_split_rend_get_quant_params_fx( + MAX_SPLIT_REND_MD_BANDS, + pred_real_bands_yaw, + pred_imag_bands_yaw, + pred_quant_pnts_yaw, + pred_quantstep_yaw_fx, + pred_1byquantstep_yaw_fx, + d_bands_yaw, + bands_pitch, + pred_real_bands_roll, + pred_imag_bands_roll, + ro_md_flag, + &num_quant_strats ); +#else + isar_split_rend_get_quant_params_fx( + MAX_SPLIT_REND_MD_BANDS, + pred_real_bands_yaw, + pred_imag_bands_yaw, + pred_quant_pnts_yaw, + pred_quantstep_yaw_fx, + pred_1byquantstep_yaw_fx, + d_bands_yaw, + bands_pitch, + pred_real_bands_roll, + pred_imag_bands_roll, + &num_quant_strats, + &num_complex_bands ); +#endif + quant_strat_bits = L_deposit_l( ceil_log_2( num_quant_strats ) ); + is_huff_coding = ISAR_SPLIT_REND_BITStream_read_int32( pBits, 1 ); + quant_strat = ISAR_SPLIT_REND_BITStream_read_int32( pBits, quant_strat_bits ); + + IF( EQ_32( is_huff_coding, 0 ) ) + { + isar_splitBinPostRendMdBase2Dec( + pBits, hBinHrSplitPostRend, + pMultiBinPoseData, + num_subframes, + pred_real_bands_yaw[quant_strat], + pred_imag_bands_yaw[quant_strat], + pred_quant_pnts_yaw[quant_strat], + d_bands_yaw[quant_strat], + bands_pitch[quant_strat], + pred_real_bands_roll[quant_strat], + pred_imag_bands_roll[quant_strat] ); + } + ELSE + { + ivas_splitBinPostRendMdHuffDec( + pBits, hBinHrSplitPostRend, + pMultiBinPoseData, + num_subframes, + pred_real_bands_yaw[quant_strat], + pred_imag_bands_yaw[quant_strat], + pred_quant_pnts_yaw[quant_strat], + d_bands_yaw[quant_strat], + bands_pitch[quant_strat], + pred_real_bands_roll[quant_strat], + pred_imag_bands_roll[quant_strat] ); + } +#ifdef SPLIT_MD_CODING_DEBUG + for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + int16_t val, ch2, val_ref; + char filename[200] = "split_md_debug_indices.bin"; + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + if ( hBinHrSplitPostRend->pose_type[pos_idx] == ANY_YAW ) + { + for ( b = 0; b < pred_real_bands_yaw[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2]; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + } + } + } + for ( b = 0; b < pred_imag_bands_yaw[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2]; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + } + } + } + for ( b = 0; b < d_bands_yaw[quant_strat]; b++ ) + { + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].gd_idx; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + } + } + else if ( hBinHrSplitPostRend->pose_type[pos_idx] == PITCH_ONLY ) + { + for ( b = 0; b < bands_pitch[quant_strat]; b++ ) + { + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].gd_idx; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].gd2_idx; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + } + } + else + { + for ( b = 0; b < pred_real_bands_roll[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2]; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + } + } + } + for ( b = 0; b < pred_imag_bands_roll[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2]; + dbgread( &val_ref, sizeof( int16_t ), 1, filename ); + if ( abs( val_ref - val ) > 0 ) + { + assert( 0 ); + } + } + } + } + } + } + } +#endif + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( pos_idx = 0; pos_idx < sub( pMultiBinPoseData->num_poses, 1 ); pos_idx++ ) + { + IF( EQ_32( hBinHrSplitPostRend->pose_type[pos_idx], ANY_YAW ) ) + { + FOR( b = 0; b < pred_imag_bands_yaw[quant_strat]; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + ivas_split_rend_unquant_md_fx( hMd, PRED_ONLY, 0, hBinHrSplitPostRend->fix_pos_rot_mat_fx[pos_idx], pred_quantstep_yaw_fx[quant_strat] ); + } + FOR( ; b < pred_real_bands_yaw[quant_strat]; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + ivas_split_rend_unquant_md_fx( hMd, PRED_ONLY, 1, hBinHrSplitPostRend->fix_pos_rot_mat_fx[pos_idx], pred_quantstep_yaw_fx[quant_strat] ); + } + FOR( ; b < MAX_SPLIT_REND_MD_BANDS; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + set32_fx( hMd->pred_mat_re_fx[ch1], 0, BINAURAL_CHANNELS ); + set32_fx( hMd->pred_mat_im_fx[ch1], 0, BINAURAL_CHANNELS ); + hMd->pred_mat_re_fx[ch1][ch1] = L_shl( 1, Q25 ); /* 1.0f in Q25 */ + move32(); + } + } + FOR( b = 0; b < d_bands_yaw[quant_strat]; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + ivas_split_rend_unquant_md_fx( hMd, COM_GAIN_ONLY, 1, hBinHrSplitPostRend->fix_pos_rot_mat_fx[pos_idx], 0 ); + } + FOR( ; b < MAX_SPLIT_REND_MD_BANDS; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + hMd->gd_fx = 0; + move32(); + } + } + ELSE IF( EQ_32( hBinHrSplitPostRend->pose_type[pos_idx], PITCH_ONLY ) ) + { + FOR( b = 0; b < bands_pitch[quant_strat]; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + ivas_split_rend_unquant_md_fx( hMd, LR_GAIN_ONLY, 1, hBinHrSplitPostRend->fix_pos_rot_mat_fx[pos_idx], 0 ); + } + FOR( ; b < MAX_SPLIT_REND_MD_BANDS; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + hMd->gd_fx = L_shl( 1, Q25 ); /* 1.0f in Q25 */ + move32(); + hMd->gd2_fx = L_shl( 1, Q25 ); /* 1.0f in Q25 */ + move32(); + } + } + ELSE + { + FOR( b = 0; b < pred_imag_bands_roll[quant_strat]; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + ivas_split_rend_unquant_md_fx( hMd, PRED_ROLL_ONLY, 0, hBinHrSplitPostRend->fix_pos_rot_mat_fx[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_Q_STEP_Q31 ); + } + FOR( ; b < pred_real_bands_roll[quant_strat]; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + ivas_split_rend_unquant_md_fx( hMd, PRED_ROLL_ONLY, 1, hBinHrSplitPostRend->fix_pos_rot_mat_fx[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_Q_STEP_Q31 ); + } + FOR( ; b < MAX_SPLIT_REND_MD_BANDS; b++ ) + { + hMd = &hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + set32_fx( hMd->pred_mat_re_fx[ch1], 0, BINAURAL_CHANNELS ); + set32_fx( hMd->pred_mat_im_fx[ch1], 0, BINAURAL_CHANNELS ); + hMd->pred_mat_re_fx[ch1][ch1] = L_shl( 1, Q25 ); /* 1.0f in Q25 */ + move32(); + } + } + } + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + float val; + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + if ( hBinHrSplitPostRend->pose_type[pos_idx] == ANY_YAW ) + { + for ( b = 0; b < pred_real_bands_yaw[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2]; + if ( fabsf( hMd->pred_mat_re_idx[ch1][ch2] - val ) > 1e-20 ) + { + assert( 0 ); + } + } + } + } + for ( b = 0; b < pred_imag_bands_yaw[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2]; + if ( fabsf( hMd->pred_mat_im_idx[ch1][ch2] - val ) > 1e-20 ) + { + assert( 0 ); + } + } + } + } + for ( b = 0; b < d_bands_yaw[quant_strat]; b++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_idx; + if ( fabsf( hMd->gd_idx - val ) > 1e-20 ) + { + assert( 0 ); + } + } + } + else if ( hBinHrSplitPostRend->pose_type[pos_idx] == PITCH_ONLY ) + { + for ( b = 0; b < bands_pitch[quant_strat]; b++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_idx; + if ( fabsf( hMd->gd_idx - val ) > 1e-20 ) + { + assert( 0 ); + } + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_idx; + if ( fabsf( hMd->gd2_idx - val ) > 1e-20 ) + { + assert( 0 ); + } + } + } + else + { + for ( b = 0; b < pred_real_bands_roll[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2]; + if ( fabsf( hMd->pred_mat_re_idx[ch1][ch2] - val ) > 1e-20 ) + { + assert( 0 ); + } + } + } + } + for ( b = 0; b < pred_imag_bands_roll[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2]; + if ( fabsf( hMd->pred_mat_im_idx[ch1][ch2] - val ) > 1e-20 ) + { + assert( 0 ); + } + } + } + } + } + } + } +#endif + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function wrap_around_angle() + * + * + *-----------------------------------------------------------------------------------------*/ +static void wrap_around_angle_fx( + Word32 *a_fx ) +{ + IF( GT_32( ( *a_fx ), 754974720 /*180.f in Q22*/ ) ) + { + *a_fx = L_sub( ( *a_fx ), 1509949440 /*360.f in Q22*/ ); + } + ELSE IF( LT_32( ( *a_fx ), L_negate( 754974720 /*180.f in Q22*/ ) ) ) + { + *a_fx = L_add( *a_fx, 1509949440 /*360.f in Q22*/ ); + } + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function wrap_around_angle() + * + * + *-----------------------------------------------------------------------------------------*/ +static void wrap_around_ypr_fx( + IVAS_QUATERNION *Quaternions ) +{ + /*only if quat is actually yaw, pitch , roll angles*/ + IF( EQ_32( Quaternions->w_fx, L_negate( 12582912 /*3.0f in Q22*/ ) ) ) + { + wrap_around_angle_fx( &Quaternions->x_fx ); + wrap_around_angle_fx( &Quaternions->y_fx ); + wrap_around_angle_fx( &Quaternions->z_fx ); + } + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function wrap_around_angle() + * + * + *-----------------------------------------------------------------------------------------*/ +static Word32 get_interp_fact_fx( + Word32 p_fx[MAX_HEAD_ROT_POSES], + const Word32 p_t_fx, + const Word16 ind[2], + Word16 *exp ) +{ + Word32 n_fx, d_fx, interp_fact_fx; + *exp = 31; + move16(); + IF( NE_16( ind[0], ind[1] ) ) + { + n_fx = L_sub( p_fx[ind[0]], p_fx[ind[1]] ); + move32(); + d_fx = L_sub( p_fx[ind[0]], p_t_fx ); + move32(); + interp_fact_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( d_fx, n_fx, exp ) ); // Q31-exp + move32(); + IF( LT_32( interp_fact_fx, 0 ) ) + { + d_fx = max( -( MAX_EXTRAPOLATION_ANGLE_Q22 ), ( min( ( MAX_EXTRAPOLATION_ANGLE_Q22 ), d_fx ) ) ); + move32(); + n_fx = L_deposit_h( getSineWord16R2( extract_l( L_shr( Mpy_32_32( n_fx, Q31_BY_360 ), 7 ) ) ) ); + move32(); + d_fx = L_deposit_h( getSineWord16R2( extract_l( L_shr( Mpy_32_32( d_fx, Q31_BY_360 ), 7 ) ) ) ); + move32(); + interp_fact_fx = L_deposit_h( BASOP_Util_Divide3232_Scale( d_fx, n_fx, exp ) ); // Q31-exp + move32(); + } + } + ELSE + { + interp_fact_fx = 0; + move32(); + } + return interp_fact_fx; +} + +/*-----------------------------------------------------------------------------------------* + * Function get_nearest_pose_ind() + * + * + *-----------------------------------------------------------------------------------------*/ +static void get_nearest_pose_ind_fx( + Word32 p[MAX_HEAD_ROT_POSES], + const Word32 p_t, + Word16 ind[2], + const Word16 num_poses ) +{ + Word32 min_diff, diff; + Word16 pos_idx; + + ind[0] = 0; + ind[1] = 0; + min_diff = 1509949440; // 360 in Q22 + + /*find the closest pose from assumed poses*/ + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + diff = L_abs( L_sub( p_t, p[pos_idx] ) ); + IF( LT_32( diff, min_diff ) ) + { + ind[0] = pos_idx; + min_diff = diff; + } + } + + min_diff = 1509949440; // 360 in Q22 + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + diff = L_abs( L_sub( p_t, p[pos_idx] ) ); + IF( LT_32( diff, min_diff ) && + GT_32( L_abs( L_sub( p[pos_idx], p[ind[0]] ) ), EPSILON_FX ) ) + { + ind[1] = pos_idx; + min_diff = diff; + } + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function get_interpolation_vars() + * + * + *-----------------------------------------------------------------------------------------*/ +static void get_interpolation_vars( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const IVAS_QUATERNION *Quaternions_ref, + const IVAS_QUATERNION *Quaternions_act, + int16_t interp_yaw_pose_idx[2], + int16_t interp_pitch_pose_idx[2], + int16_t interp_roll_pose_idx[2], + Word32 *interp_yaw_fact_fx, + Word32 *interp_pitch_fact_fx, + Word32 *interp_roll_fact_fx, + Word16 *q_yaw, + Word16 *q_pitch, + Word16 *q_roll ) +{ + IVAS_QUATERNION quaternions_diff, quaternions_ref_euler, quaternions_act_euler; + Word32 y_fx[MAX_HEAD_ROT_POSES], p_fx[MAX_HEAD_ROT_POSES], r_fx[MAX_HEAD_ROT_POSES]; + + int16_t pos_idx, num_poses; + Word16 exp; + + quaternions_diff.x_fx = 0; + quaternions_diff.y_fx = 0; + quaternions_diff.z_fx = 0; + + num_poses = pMultiBinPoseData->num_poses; + + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + quaternions_diff.x_fx = pMultiBinPoseData->relative_head_poses_fx[pos_idx][0]; + quaternions_diff.y_fx = pMultiBinPoseData->relative_head_poses_fx[pos_idx][1]; + quaternions_diff.z_fx = pMultiBinPoseData->relative_head_poses_fx[pos_idx][2]; + y_fx[pos_idx] = quaternions_diff.x_fx; + p_fx[pos_idx] = quaternions_diff.y_fx; + r_fx[pos_idx] = quaternions_diff.z_fx; + } + + /*interpolation if actual pose is not same as one of assumed poses*/ + /*get the deviation*/ + Quat2EulerDegree_fx( *Quaternions_ref, &quaternions_ref_euler.z_fx, &quaternions_ref_euler.y_fx, &quaternions_ref_euler.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + Quat2EulerDegree_fx( *Quaternions_act, &quaternions_act_euler.z_fx, &quaternions_act_euler.y_fx, &quaternions_act_euler.x_fx ); + + /*order in Quat2Euler seems to be reversed ?*/ + quaternions_diff.w_fx = -12582912; /*euler*/ //-3 in Q22 + quaternions_diff.x_fx = L_sub( quaternions_act_euler.x_fx, quaternions_ref_euler.x_fx ); + quaternions_diff.y_fx = L_sub( quaternions_act_euler.y_fx, quaternions_ref_euler.y_fx ); + quaternions_diff.z_fx = L_sub( quaternions_act_euler.z_fx, quaternions_ref_euler.z_fx ); + wrap_around_ypr_fx( &quaternions_diff ); + interp_yaw_pose_idx[0] = 0; + interp_yaw_pose_idx[1] = 0; + IF( GT_32( L_abs( quaternions_diff.x_fx ), EPSILON_FX ) ) + { + get_nearest_pose_ind_fx( y_fx, quaternions_diff.x_fx, interp_yaw_pose_idx, num_poses ); + } + *interp_yaw_fact_fx = get_interp_fact_fx( y_fx, quaternions_diff.x_fx, interp_yaw_pose_idx, &exp ); + *q_yaw = Q31 - exp; + + interp_pitch_pose_idx[0] = 0; + interp_pitch_pose_idx[1] = 0; + IF( GT_32( L_abs( quaternions_diff.y_fx ), EPSILON_FX ) ) + { + get_nearest_pose_ind_fx( p_fx, quaternions_diff.y_fx, interp_pitch_pose_idx, num_poses ); + } + *interp_pitch_fact_fx = get_interp_fact_fx( p_fx, quaternions_diff.y_fx, interp_pitch_pose_idx, &exp ); + *q_pitch = Q31 - exp; + + interp_roll_pose_idx[0] = 0; + interp_roll_pose_idx[1] = 0; + IF( GT_32( L_abs( quaternions_diff.z_fx ), EPSILON_FX ) ) + { + get_nearest_pose_ind_fx( r_fx, quaternions_diff.z_fx, interp_roll_pose_idx, num_poses ); + } + *interp_roll_fact_fx = get_interp_fact_fx( r_fx, quaternions_diff.z_fx, interp_roll_pose_idx, &exp ); + *q_roll = Q31 - exp; + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function interpolate_pred_matrix() + * + * + *-----------------------------------------------------------------------------------------*/ +static void interpolate_pred_matrix_fx( + ISAR_BIN_HR_SPLIT_REND_MD rot_md[][MAX_SPLIT_MD_SUBFRAMES][MAX_SPLIT_REND_MD_BANDS], + const Word16 sf_idx, + const Word16 band_idx, + const Word16 ind[2], + const Word32 interp_fact_fx, + Word16 intrep_norm, + Word32 mat_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *exp_mat_re, + Word32 mat_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *exp_mat_im ) +{ + Word16 ch_idx1, ch_idx2; + ISAR_BIN_HR_SPLIT_REND_MD *pRot_md; + // ord16 intrep_norm = Q_factor_L(interp_fact); + // ord32 interp_fact_fx = floatToFixed(interp_fact, intrep_norm); + Word32 diff_fx; + Word32 mix_mat_re1_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_im1_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_re2_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_im2_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 buff_exp_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], buff_exp_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + set32_fx( mix_mat_re1_fx[ch_idx1], 0, BINAURAL_CHANNELS ); + set32_fx( mix_mat_im1_fx[ch_idx1], 0, BINAURAL_CHANNELS ); + mix_mat_re1_fx[ch_idx1][ch_idx1] = ONE_IN_Q25; + + set32_fx( mix_mat_re2_fx[ch_idx1], 0, BINAURAL_CHANNELS ); + set32_fx( mix_mat_im2_fx[ch_idx1], 0, BINAURAL_CHANNELS ); + mix_mat_re2_fx[ch_idx1][ch_idx1] = ONE_IN_Q25; + } + + IF( ind[0] != 0 ) + { + pRot_md = &rot_md[ind[0] - 1][sf_idx][band_idx]; + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + FOR( ch_idx2 = 0; ch_idx2 < BINAURAL_CHANNELS; ch_idx2++ ) + { + mix_mat_re1_fx[ch_idx1][ch_idx2] = pRot_md->pred_mat_re_fx[ch_idx1][ch_idx2]; + mix_mat_im1_fx[ch_idx1][ch_idx2] = pRot_md->pred_mat_im_fx[ch_idx1][ch_idx2]; + } + } + } + + IF( ind[1] != 0 ) + { + pRot_md = &rot_md[ind[1] - 1][sf_idx][band_idx]; + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + FOR( ch_idx2 = 0; ch_idx2 < BINAURAL_CHANNELS; ch_idx2++ ) + { + mix_mat_re2_fx[ch_idx1][ch_idx2] = pRot_md->pred_mat_re_fx[ch_idx1][ch_idx2]; + mix_mat_im2_fx[ch_idx1][ch_idx2] = pRot_md->pred_mat_im_fx[ch_idx1][ch_idx2]; + } + } + } + + Word16 final_exp = 0, mat_re_exp = 0, mat_im_exp = 0; + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + FOR( ch_idx2 = 0; ch_idx2 < BINAURAL_CHANNELS; ch_idx2++ ) + { + final_exp = 0; + diff_fx = BASOP_Util_Add_Mant32Exp( mix_mat_re1_fx[ch_idx1][ch_idx2], 31 - Q25, L_negate( mix_mat_re2_fx[ch_idx1][ch_idx2] ), 31 - Q25, &final_exp ); + Word64 tmp1 = W_mult_32_32( diff_fx, interp_fact_fx ); // final_exp + (31 - intrep_norm) + Word16 tmp1_nrm = W_norm( tmp1 ); + Word32 tmp1_final = W_extract_h( W_shl( tmp1, tmp1_nrm ) ); // final_exp + (31 - intrep_norm) - tmp1_nrm + mat_re_exp = 0; + mat_re_fx[ch_idx1][ch_idx2] = BASOP_Util_Add_Mant32Exp( mix_mat_re1_fx[ch_idx1][ch_idx2], 31 - Q25, L_negate( tmp1_final ), final_exp + ( 31 - intrep_norm ) - tmp1_nrm, &mat_re_exp ); + buff_exp_re[ch_idx1][ch_idx2] = mat_re_exp; + + final_exp = 0; + diff_fx = BASOP_Util_Add_Mant32Exp( mix_mat_im1_fx[ch_idx1][ch_idx2], 31 - Q25, L_negate( mix_mat_im2_fx[ch_idx1][ch_idx2] ), 31 - Q25, &final_exp ); + Word64 tmp2 = W_mult_32_32( diff_fx, interp_fact_fx ); // final_exp + (31 - intrep_norm) + Word16 tmp2_nrm = W_norm( tmp2 ); + Word32 tmp2_final = W_extract_h( W_shl( tmp2, tmp2_nrm ) ); // final_exp + (31 - intrep_norm) - tmp1_nrm + mat_im_exp = 0; + mat_im_fx[ch_idx1][ch_idx2] = BASOP_Util_Add_Mant32Exp( mix_mat_im1_fx[ch_idx1][ch_idx2], 31 - Q25, L_negate( tmp2_final ), final_exp + ( 31 - intrep_norm ) - tmp2_nrm, &mat_im_exp ); + buff_exp_im[ch_idx1][ch_idx2] = mat_im_exp; + } + } + + Word16 max_exp_re = MIN16B; + Word16 max_exp_im = MIN16B; + FOR( Word16 i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < BINAURAL_CHANNELS; j++ ) + { + max_exp_re = max( max_exp_re, buff_exp_re[i][j] ); + max_exp_im = max( max_exp_im, buff_exp_im[i][j] ); + } + } + FOR( Word16 i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mat_re_fx[i][j] = L_shr( mat_re_fx[i][j], max_exp_re - buff_exp_re[i][j] ); + mat_im_fx[i][j] = L_shr( mat_im_fx[i][j], max_exp_im - buff_exp_im[i][j] ); + } + } + + *exp_mat_re = max_exp_re; + *exp_mat_im = max_exp_im; + + return; +} +/*-----------------------------------------------------------------------------------------* + * Function interpolate_rend_md() + * + * + *-----------------------------------------------------------------------------------------*/ + +static void interpolate_rend_md_fx( + ISAR_BIN_HR_SPLIT_REND_MD rot_md[][MAX_SPLIT_MD_SUBFRAMES][MAX_SPLIT_REND_MD_BANDS], + Word32 mix_mat_re_fx[][BINAURAL_CHANNELS], + Word16 *exp_mix_mat_re, + Word32 mix_mat_im_fx[][BINAURAL_CHANNELS], + Word16 *exp_mix_mat_im, + Word32 *gd_int_fx, + Word16 *exp_gd_int, + const Word16 sf_idx, + const Word16 band_idx, + const Word16 interp_yaw_pose_idx[2], + const Word16 interp_pitch_pose_idx[2], + const Word16 interp_roll_pose_idx[2], + const Word32 interp_yaw_fact_fx, + Word16 Q_yaw, + const Word32 interp_pitch_fact_fx, + Word16 Q_pitch, + const Word32 interp_roll_fact_fx, + Word16 Q_roll ) +{ + Word16 ch_idx1, idx1, idx2; + + Word32 mix_mat_re1_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_im1_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_re3_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_im3_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + + Word16 exp_mix_mat_re1 = 0; + Word16 exp_mix_mat_im1 = 0; + Word16 exp_mix_mat_re3 = 0; + Word16 exp_mix_mat_im3 = 0; + + Word16 ch_idx2; + Word16 exp_pitch_gain_r, exp_pitch_gain_l; + Word32 gd1_fx = 0, gd2_fx = 0; + Word32 gd3_fx = 0, gd4_fx = 0; + Word32 pitch_gain_r_fx, pitch_gain_l_fx; + Word32 diff_fx; + + Word16 exp_mat_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 exp_mat_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + + idx1 = interp_yaw_pose_idx[0]; + idx2 = interp_yaw_pose_idx[1]; + + + IF( NE_16( idx1, 0 ) || NE_16( idx2, 0 ) ) + { + interpolate_pred_matrix_fx( rot_md, sf_idx, band_idx, interp_yaw_pose_idx, interp_yaw_fact_fx, Q_yaw, mix_mat_re_fx, exp_mix_mat_re, mix_mat_im_fx, exp_mix_mat_im ); + + IF( NE_16( idx1, 0 ) ) + { + gd1_fx = rot_md[idx1 - 1][sf_idx][band_idx].gd_fx; // Q25 + } + + IF( NE_16( idx2, 0 ) ) + { + gd2_fx = rot_md[idx2 - 1][sf_idx][band_idx].gd_fx; + } + diff_fx = L_sub( gd1_fx, gd2_fx ); // Q25 + Word32 tmp1 = Mpy_32_32( diff_fx, interp_yaw_fact_fx ); // 6+Q_yaw + Word16 exp_tmp2 = 0; + Word32 tmp2 = BASOP_Util_Add_Mant32Exp( diff_fx, 31 - Q25, L_negate( tmp1 ), 6 + Q_yaw, &exp_tmp2 ); + *gd_int_fx = tmp2; + *exp_gd_int = exp_tmp2; + } + ELSE + { + /*P = P'*/ + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + FOR( Word16 j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mix_mat_re_fx[ch_idx1][j] = 0; + mix_mat_im_fx[ch_idx1][j] = 0; + mix_mat_re_fx[ch_idx1][ch_idx1] = ONE_IN_Q25; + } + } + + *exp_mix_mat_re = 6; + *exp_mix_mat_im = 6; + + *gd_int_fx = 0; + *exp_gd_int = 0; + } + + idx1 = interp_pitch_pose_idx[0]; + idx2 = interp_pitch_pose_idx[1]; + IF( NE_16( idx1, 0 ) || NE_16( idx2, 0 ) ) + { + gd1_fx = ONE_IN_Q25; + gd2_fx = ONE_IN_Q25; + + gd3_fx = ONE_IN_Q25; + gd4_fx = ONE_IN_Q25; + + IF( NE_16( idx1, 0 ) ) + { + gd1_fx = rot_md[idx1 - 1][sf_idx][band_idx].gd_fx; + gd3_fx = rot_md[idx1 - 1][sf_idx][band_idx].gd2_fx; + } + IF( NE_16( idx2, 0 ) ) + { + gd2_fx = rot_md[idx2 - 1][sf_idx][band_idx].gd_fx; + gd4_fx = rot_md[idx2 - 1][sf_idx][band_idx].gd2_fx; + } + + diff_fx = L_sub( gd1_fx, gd2_fx ); // Q25 + IF( EQ_32( diff_fx, -1 ) ) + { + diff_fx = 0; + } + Word32 tmp = Mpy_32_32( diff_fx, interp_pitch_fact_fx ); // 6 + Q_pitch + Word16 exp_tmp1 = 0; + Word32 tmp1 = BASOP_Util_Add_Mant32Exp( gd1_fx, 31 - Q25, L_negate( tmp ), 6 + 31 - Q_pitch, &exp_tmp1 ); + pitch_gain_l_fx = tmp1; + pitch_gain_l_fx = max( 0, pitch_gain_l_fx ); + exp_pitch_gain_l = exp_tmp1; + + diff_fx = L_sub( gd3_fx, gd4_fx ); + IF( EQ_32( diff_fx, -1 ) ) + { + diff_fx = 0; + } + tmp = Mpy_32_32( diff_fx, interp_pitch_fact_fx ); + exp_tmp1 = 0; + tmp1 = BASOP_Util_Add_Mant32Exp( gd3_fx, 31 - Q25, L_negate( tmp ), 6 + 31 - Q_pitch, &exp_tmp1 ); + pitch_gain_r_fx = tmp1; + pitch_gain_r_fx = max( 0, pitch_gain_r_fx ); + exp_pitch_gain_r = exp_tmp1; + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + mix_mat_re_fx[ch_idx1][0] = Mpy_32_32( mix_mat_re_fx[ch_idx1][0], pitch_gain_l_fx ); // exp_mix_mat_re + exp_pitch_gain_l + exp_mat_re[ch_idx1][0] = *exp_mix_mat_re + exp_pitch_gain_l; + mix_mat_re_fx[ch_idx1][1] = Mpy_32_32( mix_mat_re_fx[ch_idx1][1], pitch_gain_r_fx ); // exp_mix_mat_re + exp_pitch_gain_r + exp_mat_re[ch_idx1][1] = *exp_mix_mat_re + exp_pitch_gain_r; + mix_mat_im_fx[ch_idx1][0] = Mpy_32_32( mix_mat_im_fx[ch_idx1][0], pitch_gain_l_fx ); // exp_mix_mat_im + exp_pitch_gain_l + exp_mat_im[ch_idx1][0] = *exp_mix_mat_im + exp_pitch_gain_l; + mix_mat_im_fx[ch_idx1][1] = Mpy_32_32( mix_mat_im_fx[ch_idx1][1], pitch_gain_r_fx ); // exp_mix_mat_im + exp_pitch_gain_r + exp_mat_im[ch_idx1][1] = *exp_mix_mat_im + exp_pitch_gain_r; + } + + Word16 max_exp_re = MIN16B, max_exp_im = MIN16B; + FOR( Word16 i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < BINAURAL_CHANNELS; j++ ) + { + max_exp_re = max( max_exp_re, exp_mat_re[i][j] ); + max_exp_im = max( max_exp_im, exp_mat_im[i][j] ); + } + } + + FOR( Word16 i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < BINAURAL_CHANNELS; j++ ) + { + mix_mat_re_fx[i][j] = L_shr( mix_mat_re_fx[i][j], max_exp_re - exp_mat_re[i][j] ); + mix_mat_im_fx[i][j] = L_shr( mix_mat_im_fx[i][j], max_exp_im - exp_mat_im[i][j] ); + } + } + + *exp_mix_mat_re = max_exp_re; + *exp_mix_mat_im = max_exp_im; + } + ELSE + { + pitch_gain_l_fx = ONE_IN_Q25; + pitch_gain_r_fx = ONE_IN_Q25; + } + + + idx1 = interp_roll_pose_idx[0]; + idx2 = interp_roll_pose_idx[1]; + IF( NE_16( idx1, 0 ) || NE_16( idx2, 0 ) ) + { + interpolate_pred_matrix_fx( rot_md, sf_idx, band_idx, interp_roll_pose_idx, interp_roll_fact_fx, Q_roll, mix_mat_re3_fx, &exp_mix_mat_re3, mix_mat_im3_fx, &exp_mix_mat_im3 ); + + isar_mat_mult_2by2_complex_fx( mix_mat_re_fx, *exp_mix_mat_re, mix_mat_im_fx, *exp_mix_mat_im, mix_mat_re3_fx, exp_mix_mat_re3, + mix_mat_im3_fx, exp_mix_mat_im3, mix_mat_re1_fx, &exp_mix_mat_re1, mix_mat_im1_fx, &exp_mix_mat_im1 ); + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + FOR( ch_idx2 = 0; ch_idx2 < BINAURAL_CHANNELS; ch_idx2++ ) + { + mix_mat_re_fx[ch_idx1][ch_idx2] = mix_mat_re1_fx[ch_idx1][ch_idx2]; + mix_mat_im_fx[ch_idx1][ch_idx2] = mix_mat_im1_fx[ch_idx1][ch_idx2]; + } + } + *exp_mix_mat_re = exp_mix_mat_re1; + *exp_mix_mat_im = exp_mix_mat_im1; + } + + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function isar_SplitRenderer_PostRenderer() + * + * + *-----------------------------------------------------------------------------------------*/ +void isar_SplitRenderer_PostRenderer( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinPostRenderer, /* i/o: binaural renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ + Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i/o : Reference/out Binaural signals */ + const IVAS_QUATERNION Quaternion_act ) +{ + int16_t pos_idx, b, brange[2], ch_idx1; + int16_t num_md_bands, slot_idx, b2, index_slot, num_slots, sf_idx_md; + Word32 pred_out_re_fx[BINAURAL_CHANNELS], pred_out_im_fx[BINAURAL_CHANNELS], tmp_re_fx, tmp_im_fx, gd_int_fx; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + ISAR_BIN_HR_SPLIT_REND_MD rot_md_act[MAX_HEAD_ROT_POSES][MAX_SPLIT_REND_MD_BANDS]; +#else + ISAR_BIN_HR_SPLIT_REND_MD rot_md_act[1][MAX_SPLIT_REND_MD_BANDS]; +#endif + int16_t interp_yaw_pose_idx[2], interp_pitch_pose_idx[2], interp_roll_pose_idx[2]; + Word32 interp_yaw_fact_fx, interp_pitch_fact_fx, interp_roll_fact_fx; + Word16 Q_yaw = Q31, Q_pitch = Q31, Q_roll = Q31; + Word32 mix_mat_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mix_mat_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + float Cldfb_RealBuffer_Recons_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Recons_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#endif + Word16 fade_fx; + Word32 *pMix_mat_re_prev_fx[BINAURAL_CHANNELS]; + Word32 *pMix_mat_im_prev_fx[BINAURAL_CHANNELS]; + const int16_t *pBand_grouping = isar_split_rend_band_grouping; + + num_md_bands = MAX_SPLIT_REND_MD_BANDS; + + push_wmops( "isar_SplitRenderer_PostRenderer" ); + + num_slots = MAX_PARAM_SPATIAL_SUBFRAMES; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + pos_idx = MAX_HEAD_ROT_POSES - 1; +#else + pos_idx = 0; +#endif + + sf_idx_md = 0; + + get_interpolation_vars( pMultiBinPoseData, &hBinPostRenderer->QuaternionsPre[sf_idx_md], &Quaternion_act, interp_yaw_pose_idx, interp_pitch_pose_idx, interp_roll_pose_idx, &interp_yaw_fact_fx, &interp_pitch_fact_fx, &interp_roll_fact_fx, &Q_yaw, &Q_pitch, &Q_roll ); + + FOR( b = 0; b < num_md_bands; b++ ) + { + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + set_l( mix_mat_re_fx[ch_idx1], 0, BINAURAL_CHANNELS ); + set_l( mix_mat_im_fx[ch_idx1], 0, BINAURAL_CHANNELS ); + mix_mat_re_fx[ch_idx1][ch_idx1] = L_shl( 1, Q25 ); + } + + Word16 exp_gd_int = 0; + + Word16 exp_mix_mat_re = 6, exp_mix_mat_im = 6; + + interpolate_rend_md_fx( hBinPostRenderer->rot_md, mix_mat_re_fx, &exp_mix_mat_re, mix_mat_im_fx, &exp_mix_mat_im, &gd_int_fx, &exp_gd_int, sf_idx_md, b, interp_yaw_pose_idx, + interp_pitch_pose_idx, interp_roll_pose_idx, interp_yaw_fact_fx, Q_yaw, interp_pitch_fact_fx, Q_pitch, interp_roll_fact_fx, Q_roll ); + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + /*update the prediction matrix with interpolated matrix*/ + rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][0] = L_shl( mix_mat_re_fx[ch_idx1][0], exp_mix_mat_re - 6 ); // Q25 + rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][1] = L_shl( mix_mat_re_fx[ch_idx1][1], exp_mix_mat_re - 6 ); // Q25 + rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][0] = L_shl( mix_mat_im_fx[ch_idx1][0], exp_mix_mat_im - 6 ); // Q25 + rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][1] = L_shl( mix_mat_im_fx[ch_idx1][1], exp_mix_mat_im - 6 ); // Q25 + rot_md_act[pos_idx][b].gd_fx = L_shl( gd_int_fx, exp_gd_int - 6 ); // Q25 + } + } + + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES - 1; pos_idx++ ) + { + for ( b = 0; b < num_md_bands; b++ ) + { + if ( hBinPostRenderer->pose_type[pos_idx] == PITCH_ONLY ) + { + + for ( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + set_zero( hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_re[ch_idx1], BINAURAL_CHANNELS ); + set_zero( hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_im[ch_idx1], BINAURAL_CHANNELS ); + hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_re[ch_idx1][ch_idx1] = 1.0f; + } + hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_re[0][0] *= hBinPostRenderer->rot_md[pos_idx][sf_idx][b].gd; + hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_re[1][1] *= hBinPostRenderer->rot_md[pos_idx][sf_idx][b].gd2; + hBinPostRenderer->rot_md[pos_idx][sf_idx][b].gd = 0.0f; + } + else if ( hBinPostRenderer->pose_type[pos_idx] == ANY_ROLL ) + { + hBinPostRenderer->rot_md[pos_idx][sf_idx][b].gd = 0.0f; + } + + for ( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + + /*update the prediction matrix with interpolated matrix*/ + rot_md_act[pos_idx][b].pred_mat_re[ch_idx1][0] = hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_re[ch_idx1][0]; + rot_md_act[pos_idx][b].pred_mat_re[ch_idx1][1] = hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_re[ch_idx1][1]; + rot_md_act[pos_idx][b].pred_mat_im[ch_idx1][0] = hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_im[ch_idx1][0]; + rot_md_act[pos_idx][b].pred_mat_im[ch_idx1][1] = hBinPostRenderer->rot_md[pos_idx][sf_idx][b].pred_mat_im[ch_idx1][1]; + rot_md_act[pos_idx][b].gd = hBinPostRenderer->rot_md[pos_idx][sf_idx][b].gd; + } + } + } + +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) +#else + pos_idx = 0; +#endif + { + FOR( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) + { + index_slot = slot_idx; /* TODO: can be cleaned up */ + fade_fx = fade_table_fx[slot_idx]; + fade_fx = min( fade_fx, MAX_16 ); + FOR( b = 0; b < num_md_bands; b++ ) + { + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + IF( hBinPostRenderer->cf_flag ) + { + pMix_mat_re_prev_fx[ch_idx1] = hBinPostRenderer->mixer_mat_re_fx[pos_idx][b][ch_idx1]; + pMix_mat_im_prev_fx[ch_idx1] = hBinPostRenderer->mixer_mat_im_fx[pos_idx][b][ch_idx1]; + mix_mat_re_fx[ch_idx1][0] = L_add( Mpy_32_16_1( rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][0], fade_fx ), + Mpy_32_16_1( pMix_mat_re_prev_fx[ch_idx1][0], sub( 32767, fade_fx ) ) ); + mix_mat_re_fx[ch_idx1][1] = L_add( Mpy_32_16_1( rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][1], fade_fx ), + Mpy_32_16_1( pMix_mat_re_prev_fx[ch_idx1][1], sub( 32767, fade_fx ) ) ); + + mix_mat_im_fx[ch_idx1][0] = L_add( Mpy_32_16_1( rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][0], fade_fx ), + Mpy_32_16_1( pMix_mat_im_prev_fx[ch_idx1][0], sub( 32767, fade_fx ) ) ); + mix_mat_im_fx[ch_idx1][1] = L_add( Mpy_32_16_1( rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][1], fade_fx ), + Mpy_32_16_1( pMix_mat_im_prev_fx[ch_idx1][1], sub( 32767, fade_fx ) ) ); + } + ELSE + { + mix_mat_re_fx[ch_idx1][0] = rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][0]; + mix_mat_re_fx[ch_idx1][1] = rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][1]; + mix_mat_im_fx[ch_idx1][0] = rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][0]; + mix_mat_im_fx[ch_idx1][1] = rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][1]; + } + } + + brange[0] = pBand_grouping[b]; + brange[1] = pBand_grouping[b + 1]; + Word16 exp_tmp1, exp_tmp2; + FOR( b2 = brange[0]; b2 < brange[1]; b2++ ) + { + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + /* Apply prediction matrix */ + ivas_cmult_fix( Cldfb_RealBuffer_Ref_Binaural_fx[0][index_slot][b2], 25, Cldfb_ImagBuffer_Ref_Binaural_fx[0][index_slot][b2], 25, mix_mat_re_fx[0][ch_idx1], 6, mix_mat_im_fx[0][ch_idx1], 6, &tmp_re_fx, &tmp_im_fx, &exp_tmp1, &exp_tmp2 ); + // tmp_re_fx = L_shl(tmp_re_fx, sub(exp_tmp1, 6)); //Q25 + // tmp_im_fx = L_shl(tmp_im_fx, sub(exp_tmp1, 6)); //Q25 + + pred_out_re_fx[ch_idx1] = tmp_re_fx; + pred_out_im_fx[ch_idx1] = tmp_im_fx; + Word16 exp_re = exp_tmp1; + Word16 exp_im = exp_tmp2; + + ivas_cmult_fix( Cldfb_RealBuffer_Ref_Binaural_fx[1][index_slot][b2], 25, Cldfb_ImagBuffer_Ref_Binaural_fx[1][index_slot][b2], 25, mix_mat_re_fx[1][ch_idx1], 6, mix_mat_im_fx[1][ch_idx1], 6, &tmp_re_fx, &tmp_im_fx, &exp_tmp1, &exp_tmp2 ); + // tmp_re_fx = L_shl(tmp_re_fx, sub(exp_tmp1, 6)); //Q25 + // tmp_im_fx = L_shl(tmp_im_fx, sub(exp_tmp1, 6)); //Q25 + + pred_out_re_fx[ch_idx1] = BASOP_Util_Add_Mant32Exp( pred_out_re_fx[ch_idx1], exp_re, tmp_re_fx, exp_tmp1, &exp_re ); + pred_out_re_fx[ch_idx1] = L_shl( pred_out_re_fx[ch_idx1], exp_re - 25 ); + pred_out_im_fx[ch_idx1] = BASOP_Util_Add_Mant32Exp( pred_out_im_fx[ch_idx1], exp_im, tmp_im_fx, exp_tmp2, &exp_im ); + pred_out_im_fx[ch_idx1] = L_shl( pred_out_im_fx[ch_idx1], exp_im - 25 ); + } + + + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + Cldfb_RealBuffer_Recons_Binaural[pos_idx][ch_idx1][index_slot][b2] = pred_out_re[ch_idx1]; + Cldfb_ImagBuffer_Recons_Binaural[pos_idx][ch_idx1][index_slot][b2] = pred_out_im[ch_idx1]; +#else + Cldfb_RealBuffer_Ref_Binaural_fx[ch_idx1][index_slot][b2] = pred_out_re_fx[ch_idx1]; + Cldfb_ImagBuffer_Ref_Binaural_fx[ch_idx1][index_slot][b2] = pred_out_im_fx[ch_idx1]; +#endif + } + } + } + } + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) +#else + pos_idx = 0; +#endif + { + FOR( b = 0; b < num_md_bands; b++ ) + { + FOR( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + hBinPostRenderer->mixer_mat_re_fx[pos_idx][b][ch_idx1][0] = rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][0]; // Q25 + hBinPostRenderer->mixer_mat_re_fx[pos_idx][b][ch_idx1][1] = rot_md_act[pos_idx][b].pred_mat_re_fx[ch_idx1][1]; // Q25 + hBinPostRenderer->mixer_mat_im_fx[pos_idx][b][ch_idx1][0] = rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][0]; // Q25 + hBinPostRenderer->mixer_mat_im_fx[pos_idx][b][ch_idx1][1] = rot_md_act[pos_idx][b].pred_mat_im_fx[ch_idx1][1]; // Q25 + } + hBinPostRenderer->gd_mem_fx[pos_idx][b] = rot_md_act[pos_idx][b].gd_fx; // Q25 + } + } + hBinPostRenderer->cf_flag = 1; + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + { + int16_t num_cldfb_bands; + num_cldfb_bands = CLDFB_NO_CHANNELS_MAX; + for ( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) + { + index_slot = sf_idx * num_slots + slot_idx; + for ( ch_idx1 = 0; ch_idx1 < BINAURAL_CHANNELS; ch_idx1++ ) + { + mvr2r( Cldfb_RealBuffer_Recons_Binaural[MAX_HEAD_ROT_POSES - 1][ch_idx1][index_slot], Cldfb_RealBuffer_Ref_Binaural[ch_idx1][index_slot], num_cldfb_bands ); + mvr2r( Cldfb_ImagBuffer_Recons_Binaural[MAX_HEAD_ROT_POSES - 1][ch_idx1][index_slot], Cldfb_ImagBuffer_Ref_Binaural[ch_idx1][index_slot], num_cldfb_bands ); + } + } + + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + char fname[200] = "recons_out_pos"; + char tag[2]; + tag[0] = (char) ( '0' + pos_idx ); + tag[1] = '\0'; + strcat( fname, tag ); + strcat( fname, ".wav" ); + isar_log_cldfb2wav_data( + Cldfb_RealBuffer_Recons_Binaural[pos_idx], + Cldfb_ImagBuffer_Recons_Binaural[pos_idx], + hBinPostRenderer->cldfbSynReconsBinDec[pos_idx], + BINAURAL_CHANNELS, + num_cldfb_bands, + 48000, + num_slots, + sf_idx * num_slots, + fname ); + } + } +#endif + + pop_wmops(); + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function isar_rend_CldfbSplitPostRendProcessTdIn() + * + * + *-----------------------------------------------------------------------------------------*/ +static void isar_rend_CldfbSplitPostRendProcessTdIn( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const IVAS_QUATERNION QuaternionPost, + Word32 output_fx[][L_FRAME48k], + Word16 *Q_out ) +{ + int16_t ch_idx, slot_idx, num_cldfb_bands; + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX] = { 0 }; + num_cldfb_bands = hBinHrSplitPostRend->cldfbSyn[0]->no_channels; + Word16 Q_output = 11; + + /* Implement CLDFB analysis */ + FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + Scale_sig32( output_fx[ch_idx], L_FRAME48k, Q_output - Q_out[ch_idx] ); + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + Word16 Q_cldfb = Q_output; + cldfbAnalysis_ts_fx_fixed_q( &( output_fx[ch_idx][num_cldfb_bands * slot_idx] ), + Cldfb_RealBuffer_Binaural_fx[ch_idx][slot_idx], + Cldfb_ImagBuffer_Binaural_fx[ch_idx][slot_idx], + num_cldfb_bands, + hBinHrSplitPostRend->cldfbAna[ch_idx], + &Q_cldfb ); // Q_cldfb - 5 + } + } + + isar_SplitRenderer_PostRenderer( hBinHrSplitPostRend, pMultiBinPoseData, Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, QuaternionPost ); + + /* Implement CLDFB synthesis */ + FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + Word32 *RealBuffer_fx[CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 *ImagBuffer_fx[CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 scaleFactor = 31, Q_cldfb; + + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + RealBuffer_fx[slot_idx] = Cldfb_RealBuffer_Binaural_fx[ch_idx][slot_idx]; + ImagBuffer_fx[slot_idx] = Cldfb_ImagBuffer_Binaural_fx[ch_idx][slot_idx]; + scaleFactor = s_min( scaleFactor, s_min( getScaleFactor32( RealBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX ), getScaleFactor32( ImagBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX ) ) ); + } + + scaleFactor = s_min( sub( scaleFactor, 3 ), Q24 ); // guarded bits + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + Scale_sig32( RealBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX, scaleFactor ); + Scale_sig32( ImagBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX, scaleFactor ); + } + Q_cldfb = add( scaleFactor, sub( Q_output, Q5 ) ); + Scale_sig32( hBinHrSplitPostRend->cldfbSyn[ch_idx]->cldfb_state_fx, hBinHrSplitPostRend->cldfbSyn[ch_idx]->p_filter_length, sub( sub( Q_cldfb, 1 ), Q11 ) ); + cldfbSynthesis_ivas_fx( RealBuffer_fx, ImagBuffer_fx, &( output_fx[ch_idx][0] ), num_cldfb_bands * CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, hBinHrSplitPostRend->cldfbSyn[ch_idx] ); // Q_cldfb - 1 + Scale_sig32( hBinHrSplitPostRend->cldfbSyn[ch_idx]->cldfb_state_fx, hBinHrSplitPostRend->cldfbSyn[ch_idx]->p_filter_length, sub( Q11, sub( Q_cldfb, 1 ) ) ); + Q_out[ch_idx] = sub( Q_cldfb, 1 ); + } + + return; +} +/*-----------------------------------------------------------------------------------------* + * Function isar_rend_CldfbSplitPostRendProcess() + * + * + *-----------------------------------------------------------------------------------------*/ +void isar_rend_CldfbSplitPostRendProcess( + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const IVAS_QUATERNION QuaternionPost, + Word32 Cldfb_RealBuffer_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_ImagBuffer_Binaural_fx[][CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], + Word16 Q_cldfb_in, + Word32 output_fx[][L_FRAME48k], + Word16 *Q_out, + const Word16 cldfb_in_flag ) +{ + int16_t ch_idx, slot_idx, num_cldfb_bands; + + push_wmops( "isar_rend_CldfbSplitPostRendProcess" ); + + num_cldfb_bands = hBinHrSplitPostRend->cldfbSyn[0]->no_channels; + + IF( EQ_16( cldfb_in_flag, 0 ) ) + { + isar_rend_CldfbSplitPostRendProcessTdIn( hBinHrSplitPostRend, pMultiBinPoseData, QuaternionPost, output_fx, Q_out ); + pop_wmops(); + return; + } + + isar_SplitRenderer_PostRenderer( hBinHrSplitPostRend, pMultiBinPoseData, Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, QuaternionPost ); + + /* Implement CLDFB synthesis */ + FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + Word32 *RealBuffer_fx[CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 *ImagBuffer_fx[CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 scaleFactor = 31, Q_cldfb; + + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + RealBuffer_fx[slot_idx] = Cldfb_RealBuffer_Binaural_fx[ch_idx][slot_idx]; + ImagBuffer_fx[slot_idx] = Cldfb_ImagBuffer_Binaural_fx[ch_idx][slot_idx]; + scaleFactor = s_min( scaleFactor, s_min( getScaleFactor32( RealBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX ), getScaleFactor32( ImagBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX ) ) ); + } + + scaleFactor = s_min( sub( scaleFactor, 3 ), Q24 ); // guarded bits + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + Scale_sig32( RealBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX, scaleFactor ); + Scale_sig32( ImagBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX, scaleFactor ); + } + Q_cldfb = scaleFactor + Q_cldfb_in; + Scale_sig32( hBinHrSplitPostRend->cldfbSyn[ch_idx]->cldfb_state_fx, hBinHrSplitPostRend->cldfbSyn[ch_idx]->p_filter_length, sub( sub( Q_cldfb, 1 ), Q11 ) ); + cldfbSynthesis_ivas_fx( RealBuffer_fx, ImagBuffer_fx, &( output_fx[ch_idx][0] ), num_cldfb_bands * CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, hBinHrSplitPostRend->cldfbSyn[ch_idx] ); // Q_cldfb - 1 + Scale_sig32( hBinHrSplitPostRend->cldfbSyn[ch_idx]->cldfb_state_fx, hBinHrSplitPostRend->cldfbSyn[ch_idx]->p_filter_length, sub( Q11, sub( Q_cldfb, 1 ) ) ); + Q_out[ch_idx] = sub( Q_cldfb, 1 ); + } + + pop_wmops(); + return; +} + +/*-----------------------------------------------------------------------------------------* + * Function isar_init_split_post_rend_handles() + * + * + *-----------------------------------------------------------------------------------------*/ + +void isar_init_split_post_rend_handles( + ISAR_SPLIT_POST_REND_WRAPPER *hSplitRendWrapper ) +{ + hSplitRendWrapper->hBinHrSplitPostRend = NULL; + hSplitRendWrapper->hSplitBinLCLDDec = NULL; + hSplitRendWrapper->hLc3plusDec = NULL; + isar_init_multi_bin_pose_data_fx( &hSplitRendWrapper->multiBinPoseData ); + hSplitRendWrapper->first_good_frame_received = 0; + + return; +} + +#endif diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c new file mode 100644 index 000000000..2e2e19ac4 --- /dev/null +++ b/lib_isar/isar_splitRendererPre.c @@ -0,0 +1,3469 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG +#include +#endif +#include "ivas_prot.h" +#include "prot.h" +#include "lib_isar_pre_rend.h" +#include "isar_rom_post_rend.h" +#include "isar_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" +#ifdef DBG_WAV_WRITER +#include "string.h" +#endif +#include "prot_fx2.h" +#include "basop_util.h" + +/*---------------------------------------------------------------------* + * Local function declarations + *---------------------------------------------------------------------*/ +static void isar_SplitRenderer_GetRotMd_fx( + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i/o: binaural renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ + Word16 exp_cldfb_re, + Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ + Word16 exp_cldfb_im, + const Word16 low_res, + const Word16 ro_md_flag ); + +/*------------------------------------------------------------------------- + * Local functions + * + * + *------------------------------------------------------------------------*/ + +static void isar_calc_mat_det_2by2_complex_fx( + Word32 in_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 exp_in_re, + Word32 in_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 exp_in_im, + Word32 *det_re, + Word16 *exp_det_re, + Word32 *det_im, + Word16 *exp_det_im ) +{ + Word32 re1_fx, im1_fx, re2_fx, im2_fx; + + Word16 exp_re_1 = 0, exp_re_2 = 0; + Word16 exp_im_1 = 0, exp_im_2 = 0; + ivas_cmult_fix( in_re_fx[0][0], exp_in_re, in_im_fx[0][0], exp_in_im, in_re_fx[1][1], exp_in_re, in_im_fx[1][1], exp_in_im, &re1_fx, &im1_fx, &exp_re_1, &exp_im_1 ); + ivas_cmult_fix( in_re_fx[0][1], exp_in_re, in_im_fx[0][1], exp_in_im, in_re_fx[1][0], exp_in_re, in_im_fx[1][0], exp_in_im, &re2_fx, &im2_fx, &exp_re_2, &exp_im_2 ); + + Word16 exp_re_final = 0, exp_im_final = 0; + *det_re = BASOP_Util_Add_Mant32Exp( re1_fx, exp_re_1, L_negate( re2_fx ), exp_re_2, &exp_re_final ); + *det_im = BASOP_Util_Add_Mant32Exp( im1_fx, exp_im_1, L_negate( im2_fx ), exp_im_2, &exp_im_final ); + *exp_det_re = exp_re_final; + *exp_det_im = exp_im_final; + + return; +} + +static Word16 isar_is_mat_inv_2by2_complex_fx( + Word32 in_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 exp_in_re, + Word32 in_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 exp_in_im ) +{ + Word16 is_det_zero = 1; + Word32 det, det_re, det_im; + Word16 exp_det = 0, exp_det_re = 0, exp_det_im = 0; + isar_calc_mat_det_2by2_complex_fx( in_re, exp_in_re, in_im, exp_in_im, &det_re, &exp_det_re, &det_im, &exp_det_im ); + + Word64 det_re_sq = W_mult_32_32( det_re, det_re ); + Word16 det_sq_re_nrm = W_norm( det_re_sq ); + Word32 tmp1 = W_extract_h( W_shl( det_re_sq, det_sq_re_nrm ) ); + + Word64 det_im_sq = W_mult_32_32( det_im, det_im ); + Word16 det_im_nrm = W_norm( det_im_sq ); + Word32 tmp2 = W_extract_h( W_shl( det_im_sq, det_im_nrm ) ); + + det = BASOP_Util_Add_Mant32Exp( tmp1, exp_det_re + exp_det_re - det_sq_re_nrm, tmp2, exp_det_im + exp_det_im - det_im_nrm, &exp_det ); + + Word16 res = BASOP_Util_Cmp_Mant32Exp( det, exp_det, EPSILON_FX, 31 ); + IF( EQ_16( res, -1 ) ) + { + is_det_zero = 0; + } + + return is_det_zero; +} +static void isar_calc_mat_inv_2by2_complex_fx( + Word32 in_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 exp_in_re, + Word32 in_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 exp_in_im, + Word32 out_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *exp_out_re, + Word32 out_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *exp_out_im ) +{ + Word16 exp_buffer_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], exp_buffer_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + + FOR( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + exp_buffer_re[i][j] = MIN16B; + move16(); + exp_buffer_im[i][j] = MIN16B; + move16(); + } + } + Word32 det_re_fx, det_im_fx; + Word16 exp_det_re = 0, exp_det_im = 0; + move16(); + move16(); + Word32 re_fx, im_fx, det_fx; + Word16 exp_re = 0, exp_im = 0; + move16(); + move16(); + + isar_calc_mat_det_2by2_complex_fx( in_re_fx, exp_in_re, in_im_fx, exp_in_im, &det_re_fx, &exp_det_re, &det_im_fx, &exp_det_im ); + + Word16 tmp1 = W_norm( W_mult_32_32( det_re_fx, det_re_fx ) ); + Word32 tmp2 = W_extract_h( W_shl( W_mult_32_32( det_re_fx, det_re_fx ), tmp1 ) ); // 2*exp_det_re - tmp1 + Word16 tmp3 = W_norm( W_mult_32_32( det_im_fx, det_im_fx ) ); + Word32 tmp4 = W_extract_h( W_shl( W_mult_32_32( det_im_fx, det_im_fx ), tmp3 ) ); // 2*exp_im_re - tmp3 + Word16 exp_det = 0; + det_fx = BASOP_Util_Add_Mant32Exp( tmp2, 2 * exp_det_re - tmp1, tmp4, 2 * exp_det_im - tmp3, &exp_det ); + + Word16 exp_tmp5 = 0; + Word16 tmp5 = BASOP_Util_Divide3232_Scale( ONE_IN_Q30, det_fx, &exp_tmp5 ); + exp_det = add( exp_tmp5, sub( 1, exp_det ) ); + det_fx = L_deposit_h( tmp5 ); + +#ifdef DEBUGGING + /* assert to catch cases when input is singular matrix */ + assert( GT_32( det_fx, 0 ) ); +#endif + + exp_re = 0; + exp_im = 0; + move16(); + move16(); + ivas_cmult_fix( det_re_fx, exp_det_re, L_negate( det_im_fx ), exp_det_im, in_re_fx[1][1], exp_in_re, in_im_fx[1][1], exp_in_im, &re_fx, &im_fx, &exp_re, &exp_im ); + + Word64 tmp7 = W_mult_32_32( re_fx, det_fx ); + Word16 tmp7_nrm = W_norm( tmp7 ); + out_re_fx[0][0] = W_extract_h( W_shl( tmp7, tmp7_nrm ) ); // exp_re + exp_det - tmp7_nrm + move32(); + Word64 tmp8 = W_mult_32_32( im_fx, det_fx ); + Word16 tmp8_nrm = W_norm( tmp8 ); + out_im_fx[0][0] = W_extract_h( W_shl( tmp8, tmp8_nrm ) ); // exp_im + exp_det - tmp8_nrm + move32(); + + exp_buffer_re[0][0] = add( exp_re, sub( exp_det, tmp7_nrm ) ); + move16(); + exp_buffer_im[0][0] = add( exp_im, sub( exp_det, tmp8_nrm ) ); + move16(); + + ivas_cmult_fix( det_re_fx, exp_det_re, L_negate( det_im_fx ), exp_det_im, in_re_fx[0][1], exp_in_re, in_im_fx[0][1], exp_in_im, &re_fx, &im_fx, &exp_re, &exp_im ); + + Word64 tmp9 = W_mult_32_32( L_negate( re_fx ), det_fx ); + Word16 tmp9_nrm = W_norm( tmp9 ); + out_re_fx[0][1] = W_extract_h( W_shl( tmp9, tmp9_nrm ) ); + Word64 tmp10 = W_mult_32_32( L_negate( im_fx ), det_fx ); + Word16 tmp10_nrm = W_norm( tmp10 ); + out_im_fx[0][1] = W_extract_h( W_shl( tmp10, tmp10_nrm ) ); + + exp_buffer_re[0][1] = add( exp_re, sub( exp_det, tmp9_nrm ) ); + exp_buffer_im[0][1] = add( exp_im, sub( exp_det, tmp10_nrm ) ); + + ivas_cmult_fix( det_re_fx, exp_det_re, L_negate( det_im_fx ), exp_det_im, in_re_fx[1][0], exp_in_re, in_im_fx[1][0], exp_in_im, &re_fx, &im_fx, &exp_re, &exp_im ); + + + Word64 tmp11 = W_mult_32_32( L_negate( re_fx ), det_fx ); + Word16 tmp11_nrm = W_norm( tmp11 ); + out_re_fx[1][0] = W_extract_h( W_shl( tmp11, tmp11_nrm ) ); + Word64 tmp12 = W_mult_32_32( L_negate( im_fx ), det_fx ); + Word16 tmp12_nrm = W_norm( tmp12 ); + out_im_fx[1][0] = W_extract_h( W_shl( tmp12, tmp12_nrm ) ); + + exp_buffer_re[1][0] = add( exp_re, sub( exp_det, tmp11_nrm ) ); + move16(); + exp_buffer_im[1][0] = add( exp_im, sub( exp_det, tmp12_nrm ) ); + move16(); + + ivas_cmult_fix( det_re_fx, exp_det_re, L_negate( det_im_fx ), exp_det_im, in_re_fx[0][0], exp_in_re, in_im_fx[0][0], exp_in_im, &re_fx, &im_fx, &exp_re, &exp_im ); + + Word64 tmp13 = W_mult_32_32( re_fx, det_fx ); + Word16 tmp13_nrm = W_norm( tmp13 ); + out_re_fx[1][1] = W_extract_h( W_shl( tmp13, tmp13_nrm ) ); + move32(); + + Word64 tmp14 = W_mult_32_32( im_fx, det_fx ); + Word16 tmp14_nrm = W_norm( tmp14 ); + out_im_fx[1][1] = W_extract_h( W_shl( tmp14, tmp14_nrm ) ); + move32(); + + exp_buffer_re[1][1] = add( exp_re, sub( exp_det, tmp13_nrm ) ); + move16(); + exp_buffer_im[1][1] = add( exp_im, sub( exp_det, tmp14_nrm ) ); + move16(); + + Word16 max_exp_re = MIN16B, max_exp_im = MIN16B; + FOR( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + max_exp_re = s_max( max_exp_re, exp_buffer_re[i][j] ); + max_exp_im = s_max( max_exp_im, exp_buffer_im[i][j] ); + } + } + + FOR( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + out_re_fx[i][j] = L_shr( out_re_fx[i][j], max_exp_re - exp_buffer_re[i][j] ); + move32(); + out_im_fx[i][j] = L_shr( out_im_fx[i][j], max_exp_im - exp_buffer_im[i][j] ); + move32(); + } + } + + *exp_out_re = max_exp_re; + move16(); + *exp_out_im = max_exp_im; + move16(); + + return; +} +static void ComputePredMat_fx( + Word32 cov_ii_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_re, + Word32 cov_ii_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_im, + Word32 cov_io_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_io_re, + Word32 cov_io_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_io_im, + Word32 pred_mat_re_fx[][BINAURAL_CHANNELS], + Word16 *exp_pred_mat_re, + Word32 pred_mat_im_fx[][BINAURAL_CHANNELS], + Word16 *exp_pred_mat_im, + const Word16 num_chs, + const Word16 real_only ) +{ + Word32 cov_ii_local_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 cov_ii_inv_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 cov_ii_inv_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 exp_cov_ii_local_re = 0, exp_cov_ii_inv_re = 0, exp_cov_ii_inv_im = 0; + Word32 trace_cov_fx; + + Word16 i, j; + + trace_cov_fx = 0; + Word16 exp_trace_cov = 0; + FOR( i = 0; i < num_chs; i++ ) + { + trace_cov_fx = L_add( trace_cov_fx, L_shr( cov_ii_re_fx[i][i], 1 ) ); + } + exp_trace_cov = add( exp_cov_ii_re, 1 ); + + trace_cov_fx = L_max( 0, trace_cov_fx ); + Word16 flag = BASOP_Util_Cmp_Mant32Exp( trace_cov_fx, exp_cov_ii_re, EPSILON_FX, 0 ); + IF( EQ_16( flag, negate( 1 ) ) ) + { + FOR( i = 0; i < num_chs; i++ ) + { + /* protection from cases when variance of ref channels is very small */ + set32_fx( pred_mat_re_fx[i], 0, BINAURAL_CHANNELS ); + set32_fx( pred_mat_im_fx[i], 0, BINAURAL_CHANNELS ); + } + return; + } + + Word16 buff_exp[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + buff_exp[i][j] = 0; + move16(); + } + } + + FOR( i = 0; i < num_chs; i++ ) + { + Copy32( cov_ii_re_fx[i], cov_ii_local_re_fx[i], num_chs ); + set16_fx( buff_exp[i], exp_cov_ii_re, num_chs ); + } + + Word32 tmp = 0; + FOR( i = 0; i < num_chs; i++ ) + { + tmp = Mpy_32_32( trace_cov_fx, 214748 ); // exp_trace_cov + Word16 exp_tmp = 0; + cov_ii_local_re_fx[i][i] = BASOP_Util_Add_Mant32Exp( cov_ii_re_fx[i][i], exp_cov_ii_re, tmp, exp_trace_cov, &exp_tmp ); + move32(); + buff_exp[i][i] = exp_tmp; + move16(); + } + + Word16 max_exp = MIN16B; + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 2; j++ ) + { + max_exp = max( max_exp, buff_exp[i][j] ); + } + } + + FOR( i = 0; i < num_chs; i++ ) + { + FOR( j = 0; j < num_chs; j++ ) + { + cov_ii_local_re_fx[i][j] = L_shr( cov_ii_local_re_fx[i][j], max_exp - buff_exp[i][j] ); + move32(); + } + } + + exp_cov_ii_local_re = max_exp; + move16(); + + IF( isar_is_mat_inv_2by2_complex_fx( cov_ii_local_re_fx, exp_cov_ii_local_re, cov_ii_im_fx, exp_cov_ii_im ) ) + { + isar_calc_mat_inv_2by2_complex_fx( cov_ii_local_re_fx, exp_cov_ii_local_re, cov_ii_im_fx, exp_cov_ii_im, cov_ii_inv_re_fx, &exp_cov_ii_inv_re, cov_ii_inv_im_fx, &exp_cov_ii_inv_im ); + isar_mat_mult_2by2_complex_fx( cov_ii_inv_re_fx, exp_cov_ii_inv_re, cov_ii_inv_im_fx, exp_cov_ii_inv_im, cov_io_re_fx, exp_cov_io_re, cov_io_im_fx, exp_cov_io_im, pred_mat_re_fx, exp_pred_mat_re, pred_mat_im_fx, exp_pred_mat_im ); + } + ELSE + { + Word16 max_var_idx; + FOR( i = 0; i < num_chs; i++ ) + { + set32_fx( pred_mat_re_fx[i], 0, BINAURAL_CHANNELS ); + set32_fx( pred_mat_im_fx[i], 0, BINAURAL_CHANNELS ); + } + + max_var_idx = 0; + move16(); + IF( GT_32( cov_ii_local_re_fx[1][1], cov_ii_local_re_fx[0][0] ) ) + { + max_var_idx = 1; + } + + Word16 tmp1 = 0, exp_tmp1 = 0; + move16(); + move16(); + Word16 tmp2 = 0, exp_tmp2 = 0; + move16(); + move16(); + Word16 flag1 = BASOP_Util_Cmp_Mant32Exp( cov_ii_local_re_fx[max_var_idx][max_var_idx], exp_cov_ii_local_re, EPSILON_FX, 0 ); + IF( EQ_16( flag1, 1 ) ) + { + Word16 pred_mat_buf_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], pred_mat_buf_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + set16_fx( pred_mat_buf_re[i], *exp_pred_mat_re, BINAURAL_CHANNELS ); + set16_fx( pred_mat_buf_im[i], *exp_pred_mat_im, BINAURAL_CHANNELS ); + } + FOR( j = 0; j < num_chs; j++ ) + { + tmp1 = BASOP_Util_Divide3232_Scale( cov_io_re_fx[max_var_idx][j], cov_ii_local_re_fx[max_var_idx][max_var_idx], &exp_tmp1 ); + exp_tmp1 = exp_tmp1 + ( exp_cov_io_re - exp_cov_ii_local_re ); + tmp2 = BASOP_Util_Divide3232_Scale( cov_io_im_fx[max_var_idx][j], cov_ii_local_re_fx[max_var_idx][max_var_idx], &exp_tmp2 ); + exp_tmp2 = exp_tmp2 + ( exp_cov_io_im - exp_cov_ii_local_re ); + pred_mat_re_fx[max_var_idx][j] = tmp1; + move32(); + pred_mat_im_fx[max_var_idx][j] = tmp2; + move32(); + pred_mat_buf_re[max_var_idx][j] = exp_tmp1; + move16(); + pred_mat_buf_im[max_var_idx][j] = exp_tmp2; + move16(); + } + + Word16 max_re = MIN16B, max_im = MIN16B; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + + max_re = s_max( max_re, pred_mat_buf_re[i][j] ); + move16(); + max_im = s_max( max_im, pred_mat_buf_im[i][j] ); + move16(); + } + } + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + + pred_mat_re_fx[i][j] = L_shr( pred_mat_re_fx[i][j], max_re - pred_mat_buf_re[i][j] ); + move32(); + pred_mat_im_fx[i][j] = L_shr( pred_mat_im_fx[i][j], max_im - pred_mat_buf_im[i][j] ); + move32(); + } + } + + *exp_pred_mat_re = max_re; + move16(); + *exp_pred_mat_im = max_im; + move16(); + } + } + + IF( real_only ) + { + FOR( i = 0; i < num_chs; i++ ) + { + set32_fx( pred_mat_im_fx[i], 0, BINAURAL_CHANNELS ); + } + } + + return; +} +static void ComputePostPredCov_fx( + Word32 cov_ii_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_re, + Word32 cov_ii_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_im, + Word32 pred_mat_re_fx[][BINAURAL_CHANNELS], + Word16 exp_pred_mat_re, + Word32 pred_mat_im_fx[][BINAURAL_CHANNELS], + Word16 exp_pred_mat_im, + Word32 postpred_cov_re_fx[][BINAURAL_CHANNELS], + Word16 *exp_postpred_cov_re, + Word16 num_chs ) +{ + Word16 i, j; + Word32 dmx_mat_conj_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 dmx_mat_conj_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 temp_mat_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 temp_mat_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 postpred_cov_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 exp_postpred_cov_im = 0; + Word16 exp_temp_mat_re = 0, exp_temp_mat_im = 0; + + assert( num_chs == BINAURAL_CHANNELS ); + + FOR( i = 0; i < num_chs; i++ ) + { + FOR( j = 0; j < num_chs; j++ ) + { + dmx_mat_conj_re_fx[i][j] = pred_mat_re_fx[j][i]; + move32(); + dmx_mat_conj_im_fx[i][j] = L_negate( pred_mat_im_fx[j][i] ); + move32(); + + temp_mat_re_fx[i][j] = pred_mat_re_fx[i][j]; + move32(); + temp_mat_im_fx[i][j] = pred_mat_im_fx[i][j]; + move32(); + } + set32_fx( postpred_cov_re_fx[i], 0, BINAURAL_CHANNELS ); + } + isar_mat_mult_2by2_complex_fx( dmx_mat_conj_re_fx, exp_pred_mat_re, dmx_mat_conj_im_fx, exp_pred_mat_im, cov_ii_re_fx, exp_cov_ii_re, cov_ii_im_fx, exp_cov_ii_im, temp_mat_re_fx, &exp_temp_mat_re, temp_mat_im_fx, &exp_temp_mat_im ); + isar_mat_mult_2by2_complex_fx( temp_mat_re_fx, exp_temp_mat_re, temp_mat_im_fx, exp_temp_mat_im, pred_mat_re_fx, exp_pred_mat_re, pred_mat_im_fx, exp_pred_mat_im, postpred_cov_re_fx, exp_postpred_cov_re, postpred_cov_im_fx, &exp_postpred_cov_im ); + + /* 2x2 mult */ + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < i; j++ ) + { + postpred_cov_re_fx[i][j] = postpred_cov_re_fx[j][i]; + move32(); + } + } + + return; +} +static void ComputeBandedCrossCov_fx( + Word32 Cldfb_RealBuffer1_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_re_1, + Word32 Cldfb_ImagBuffer1_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_im_1, + const Word16 ch_start_idx1, + Word32 Cldfb_RealBuffer2_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_re_2, + Word32 Cldfb_ImagBuffer2_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_im_2, + const Word16 ch_start_idx2, + Word32 out_cov_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *exp_out_cov_re, + Word32 out_cov_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 *exp_out_cov_im, + const Word16 num_chs, + const Word16 *pBand_grouping, + const Word16 num_slots, + const Word16 start_slot_idx, + const Word16 md_band_idx, + const Word16 real_only ) +{ + Word16 sf, cldfb_band_idx, ch_idx1, ch_idx2; + Word16 brange[2]; + + FOR( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ ) + { + set_l( out_cov_re_fx[ch_idx1], 0, num_chs ); + set_l( out_cov_im_fx[ch_idx1], 0, num_chs ); + } + + brange[0] = pBand_grouping[md_band_idx]; + move16(); + brange[1] = pBand_grouping[md_band_idx + 1]; + move16(); + Word16 exp_buff_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], exp_buff_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + FOR( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ ) + { + FOR( ch_idx2 = 0; ch_idx2 < num_chs; ch_idx2++ ) + { + Word32 tmp_a = out_cov_re_fx[ch_idx1][ch_idx2], tmp_b = out_cov_im_fx[ch_idx1][ch_idx2]; + Word16 exp_tmp_a = 0, exp_tmp_b = 0; + IF( EQ_16( real_only, 0 ) ) + { + FOR( sf = start_slot_idx; sf < add( start_slot_idx, num_slots ); sf++ ) + { + FOR( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ ) + { + Word64 tmp1 = W_mult_32_32( Cldfb_RealBuffer1_fx[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx], Cldfb_RealBuffer2_fx[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp1_nrm = W_norm( tmp1 ); + Word32 tmp1_final = W_extract_h( W_shl( tmp1, tmp1_nrm ) ); + + Word64 tmp2 = W_mult_32_32( Cldfb_ImagBuffer1_fx[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx], Cldfb_ImagBuffer2_fx[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp2_nrm = W_norm( tmp2 ); + Word32 tmp2_final = W_extract_h( W_shl( tmp2, tmp2_nrm ) ); + + Word16 exp_tmp3 = 0; + Word32 tmp3 = BASOP_Util_Add_Mant32Exp( tmp1_final, exp_cldfb_re_1 + exp_cldfb_re_2 - tmp1_nrm, tmp2_final, exp_cldfb_im_1 + exp_cldfb_im_2 - tmp2_nrm, &exp_tmp3 ); + Word16 exp_tmp_a_tmp = 0; + tmp_a = BASOP_Util_Add_Mant32Exp( tmp_a, exp_tmp_a, tmp3, exp_tmp3, &exp_tmp_a_tmp ); + exp_tmp_a = exp_tmp_a_tmp; + + Word64 tmp4 = W_mult_32_32( Cldfb_RealBuffer1_fx[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx], Cldfb_ImagBuffer2_fx[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp4_nrm = W_norm( tmp4 ); + Word32 tmp4_final = W_extract_h( W_shl( tmp4, tmp4_nrm ) ); // exp_cldfb_re_1 + exp_cldfb_im_2 - tmp4_nrm + + Word64 tmp5 = W_mult_32_32( Cldfb_ImagBuffer1_fx[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx], Cldfb_RealBuffer2_fx[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp5_nrm = W_norm( tmp5 ); + Word32 tmp5_final = W_extract_h( W_shl( tmp5, tmp5_nrm ) ); // exp_cldfb_im_1 + exp_cldfb_re_2 - tmp5_nrm + + Word16 exp_tmp6 = 0; + Word32 tmp6 = BASOP_Util_Add_Mant32Exp( tmp4_final, exp_cldfb_re_1 + exp_cldfb_im_2 - tmp4_nrm, L_negate( tmp5_final ), exp_cldfb_im_1 + exp_cldfb_re_2 - tmp5_nrm, &exp_tmp6 ); + Word16 exp_tmp_b_tmp = 0; + tmp_b = BASOP_Util_Add_Mant32Exp( tmp_b, exp_tmp_b, tmp6, exp_tmp6, &exp_tmp_b_tmp ); + exp_tmp_b = exp_tmp_b_tmp; + } + } + } + ELSE + { + FOR( sf = start_slot_idx; sf < add( start_slot_idx, num_slots ); sf++ ) + { + FOR( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ ) + { + Word64 tmp1 = W_mult_32_32( Cldfb_RealBuffer1_fx[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx], Cldfb_RealBuffer2_fx[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp1_nrm = W_norm( tmp1 ); + Word32 tmp1_final = W_extract_h( W_shl( tmp1, tmp1_nrm ) ); + + Word64 tmp2 = W_mult_32_32( Cldfb_ImagBuffer1_fx[ch_start_idx1 + ch_idx1][sf][cldfb_band_idx], Cldfb_ImagBuffer2_fx[ch_start_idx2 + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp2_nrm = W_norm( tmp2 ); + Word32 tmp2_final = W_extract_h( W_shl( tmp2, tmp2_nrm ) ); + + Word16 exp_tmp3 = 0; + Word32 tmp3 = BASOP_Util_Add_Mant32Exp( tmp1_final, exp_cldfb_re_1 + exp_cldfb_re_2 - tmp1_nrm, tmp2_final, exp_cldfb_im_1 + exp_cldfb_im_2 - tmp2_nrm, &exp_tmp3 ); + Word16 exp_tmp_a_tmp = 0; + tmp_a = BASOP_Util_Add_Mant32Exp( tmp_a, exp_tmp_a, tmp3, exp_tmp3, &exp_tmp_a_tmp ); + exp_tmp_a = exp_tmp_a_tmp; + + tmp_b = 0; + exp_tmp_b = 0; + } + } + } + out_cov_re_fx[ch_idx1][ch_idx2] = tmp_a; + move32(); + out_cov_im_fx[ch_idx1][ch_idx2] = tmp_b; + move32(); + exp_buff_re[ch_idx1][ch_idx2] = exp_tmp_a; + move32(); + exp_buff_im[ch_idx1][ch_idx2] = exp_tmp_b; + move32(); + } + } + /*make common exponent*/ + Word16 max_cov_re = 0, max_cov_im = 0; + FOR( int i = 0; i < num_chs; i++ ) + { + FOR( int j = 0; j < num_chs; j++ ) + { + max_cov_re = max( max_cov_re, exp_buff_re[i][j] ); + max_cov_im = max( max_cov_im, exp_buff_im[i][j] ); + } + } + FOR( int i = 0; i < num_chs; i++ ) + { + FOR( int j = 0; j < num_chs; j++ ) + { + out_cov_re_fx[i][j] = L_shr( out_cov_re_fx[i][j], max_cov_re - exp_buff_re[i][j] ); + move32(); + out_cov_im_fx[i][j] = L_shr( out_cov_im_fx[i][j], max_cov_im - exp_buff_im[i][j] ); + move32(); + } + } + + *exp_out_cov_re = max_cov_re; + *exp_out_cov_im = max_cov_im; + + return; +} +static void ComputeBandedCov_fx( + Word32 Cldfb_RealBuffer_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_re, + Word32 Cldfb_ImagBuffer_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_im, + const Word16 ch_start_idx, + Word32 out_cov_re_fx[][BINAURAL_CHANNELS], + Word16 *exp_cov_re, + Word32 out_cov_im_fx[][BINAURAL_CHANNELS], + Word16 *exp_cov_im, + const Word16 num_chs, + const Word16 *pBand_grouping, + const Word16 num_slots, + const Word16 start_slot_idx, + const Word16 md_band_idx, + const Word16 real_only ) +{ + Word16 sf, cldfb_band_idx, ch_idx1, ch_idx2; + Word16 brange[2]; + + FOR( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ ) + { + set32_fx( out_cov_re_fx[ch_idx1], 0, num_chs ); + set32_fx( out_cov_im_fx[ch_idx1], 0, num_chs ); + } + + brange[0] = pBand_grouping[md_band_idx]; + move16(); + brange[1] = pBand_grouping[md_band_idx + 1]; + move16(); + + Word16 exp_buff_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], exp_buff_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + FOR( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + exp_buff_re[i][j] = 0; + move16(); + exp_buff_im[i][j] = 0; + move16(); + } + } + + FOR( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ ) + { + FOR( ch_idx2 = 0; ch_idx2 <= ch_idx1; ch_idx2++ ) + { + Word32 tmp_a = out_cov_re_fx[ch_idx1][ch_idx2]; + Word32 tmp_b = out_cov_im_fx[ch_idx1][ch_idx2]; + Word16 exp_tmp_a = 0, exp_tmp_b = 0; + test(); + IF( ( NE_16( ch_idx2, ch_idx1 ) ) && ( EQ_16( real_only, 0 ) ) ) + { + FOR( sf = start_slot_idx; sf < add( start_slot_idx, num_slots ); sf++ ) + { + FOR( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ ) + { + Word64 tmp1 = W_mult_32_32( Cldfb_RealBuffer_fx[ch_start_idx + ch_idx1][sf][cldfb_band_idx], Cldfb_RealBuffer_fx[ch_start_idx + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp1_nrm = W_norm( tmp1 ); + Word32 tmp1_final = W_extract_h( W_shl( tmp1, tmp1_nrm ) ); // exp_cldfb_re + exp_cldfb_re - tmp1_nrm + + Word64 tmp2 = W_mult_32_32( Cldfb_ImagBuffer_fx[ch_start_idx + ch_idx1][sf][cldfb_band_idx], Cldfb_ImagBuffer_fx[ch_start_idx + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp2_nrm = W_norm( tmp2 ); + Word32 tmp2_final = W_extract_h( W_shl( tmp2, tmp2_nrm ) ); // exp_cldfb_im + exp_cldfb_im - tmp2_nrm + + Word16 exp_tmp3 = 0; + Word32 tmp3 = BASOP_Util_Add_Mant32Exp( tmp1_final, exp_cldfb_re + exp_cldfb_re - tmp1_nrm, tmp2_final, exp_cldfb_im + exp_cldfb_im - tmp2_nrm, &exp_tmp3 ); + Word16 exp_tmp_a_tmp = 0; + tmp_a = BASOP_Util_Add_Mant32Exp( tmp_a, exp_tmp_a, tmp3, exp_tmp3, &exp_tmp_a_tmp ); + exp_tmp_a = exp_tmp_a_tmp; + + Word64 tmp4 = W_mult_32_32( Cldfb_RealBuffer_fx[ch_start_idx + ch_idx1][sf][cldfb_band_idx], Cldfb_ImagBuffer_fx[ch_start_idx + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp4_nrm = W_norm( tmp4 ); + Word32 tmp4_final = W_extract_h( W_shl( tmp4, tmp4_nrm ) ); // exp_cldfb_re + exp_cldfb_im - tmp4_nrm + + Word64 tmp5 = W_mult_32_32( Cldfb_ImagBuffer_fx[ch_start_idx + ch_idx1][sf][cldfb_band_idx], Cldfb_RealBuffer_fx[ch_start_idx + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp5_nrm = W_norm( tmp5 ); + Word32 tmp5_final = W_extract_h( W_shl( tmp5, tmp5_nrm ) ); // exp_cldfb_im + exp_cldfb_re - tmp5_nrm + + Word16 exp_tmp6 = 0; + Word32 tmp6 = BASOP_Util_Add_Mant32Exp( tmp4_final, exp_cldfb_re + exp_cldfb_im - tmp4_nrm, L_negate( tmp5_final ), exp_cldfb_im + exp_cldfb_re - tmp5_nrm, &exp_tmp6 ); + Word16 exp_tmp_b_tmp = 0; + tmp_b = BASOP_Util_Add_Mant32Exp( tmp_b, exp_tmp_b, tmp6, exp_tmp6, &exp_tmp_b_tmp ); + exp_tmp_b = exp_tmp_b_tmp; + } + } + } + ELSE + { + FOR( sf = start_slot_idx; sf < add( start_slot_idx, num_slots ); sf++ ) + { + FOR( cldfb_band_idx = brange[0]; cldfb_band_idx < brange[1]; cldfb_band_idx++ ) + { + Word64 tmp1 = W_mult_32_32( Cldfb_RealBuffer_fx[ch_start_idx + ch_idx1][sf][cldfb_band_idx], Cldfb_RealBuffer_fx[ch_start_idx + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp1_nrm = W_norm( tmp1 ); + Word32 tmp1_final = W_extract_h( W_shl( tmp1, tmp1_nrm ) ); // exp_cldfb_re + exp_cldfb_re - tmp1_nrm + + Word64 tmp2 = W_mult_32_32( Cldfb_ImagBuffer_fx[ch_start_idx + ch_idx1][sf][cldfb_band_idx], Cldfb_ImagBuffer_fx[ch_start_idx + ch_idx2][sf][cldfb_band_idx] ); + Word16 tmp2_nrm = W_norm( tmp2 ); + Word32 tmp2_final = W_extract_h( W_shl( tmp2, tmp2_nrm ) ); // exp_cldfb_im + exp_cldfb_im - tmp2_nrm + + Word16 exp_tmp3 = 0; + Word32 tmp3 = BASOP_Util_Add_Mant32Exp( tmp1_final, exp_cldfb_re + exp_cldfb_re - tmp1_nrm, tmp2_final, exp_cldfb_im + exp_cldfb_im - tmp2_nrm, &exp_tmp3 ); + + Word16 exp_tmp_a_tmp = 0; + tmp_a = BASOP_Util_Add_Mant32Exp( tmp_a, exp_tmp_a, tmp3, exp_tmp3, &exp_tmp_a_tmp ); + exp_tmp_a = exp_tmp_a_tmp; + + tmp_b = 0; + exp_tmp_b = 0; + } + } + } + out_cov_re_fx[ch_idx1][ch_idx2] = tmp_a; + move32(); + exp_buff_re[ch_idx1][ch_idx2] = exp_tmp_a; + move32(); + + out_cov_im_fx[ch_idx1][ch_idx2] = tmp_b; + move32(); + exp_buff_im[ch_idx1][ch_idx2] = exp_tmp_b; + move32(); + } + } + + Word16 exp_max_re = MIN16B, exp_max_im = MIN16B; + FOR( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + exp_max_re = max( exp_max_re, exp_buff_re[i][j] ); + exp_max_im = max( exp_max_im, exp_buff_im[i][j] ); + } + } + + FOR( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + out_cov_re_fx[i][j] = L_shr( out_cov_re_fx[i][j], exp_max_re - exp_buff_re[i][j] ); + move32(); + out_cov_im_fx[i][j] = L_shr( out_cov_im_fx[i][j], exp_max_im - exp_buff_im[i][j] ); + move32(); + } + } + + FOR( ch_idx1 = 0; ch_idx1 < num_chs; ch_idx1++ ) + { + FOR( ch_idx2 = add( ch_idx1, 1 ); ch_idx2 < num_chs; ch_idx2++ ) + { + out_cov_re_fx[ch_idx1][ch_idx2] = out_cov_re_fx[ch_idx2][ch_idx1]; + move32(); + out_cov_im_fx[ch_idx1][ch_idx2] = L_negate( out_cov_im_fx[ch_idx2][ch_idx1] ); + move32(); + } + } + + *exp_cov_re = exp_max_re; + *exp_cov_im = exp_max_im; + + return; +} +static Word32 GetNormFact_fx( + Word32 cov_ii_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_re, + Word32 cov_ii_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_im, + Word32 cov_io_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_io_re, + Word32 cov_io_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_io_im, + Word32 cov_oo_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_oo_re, + Word16 *exp_norm_fact_fx ) +{ + Word16 i, j; + Word32 norm_fact_fx = 0, abs_val_fx; + Word16 exp_abs_val = 0, exp_norm_fact = 0; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + ivas_calculate_abs_fx( cov_ii_re_fx[i][j], exp_cov_ii_re, cov_ii_im_fx[i][j], exp_cov_ii_im, &abs_val_fx, &exp_abs_val ); + Word16 res_1 = BASOP_Util_Cmp_Mant32Exp( norm_fact_fx, exp_norm_fact, abs_val_fx, exp_abs_val ); + IF( EQ_16( res_1, negate( 1 ) ) ) + { + norm_fact_fx = abs_val_fx; + exp_norm_fact = exp_abs_val; + } + + ivas_calculate_abs_fx( cov_io_re_fx[i][j], exp_cov_io_re, cov_io_im_fx[i][j], exp_cov_io_im, &abs_val_fx, &exp_abs_val ); + res_1 = BASOP_Util_Cmp_Mant32Exp( norm_fact_fx, exp_norm_fact, abs_val_fx, exp_abs_val ); + IF( EQ_16( res_1, negate( 1 ) ) ) + { + norm_fact_fx = abs_val_fx; + exp_norm_fact = exp_abs_val; + } + ivas_calculate_rabs_fx( cov_oo_re_fx[i][j], exp_cov_oo_re, &abs_val_fx, &exp_abs_val ); + res_1 = BASOP_Util_Cmp_Mant32Exp( norm_fact_fx, exp_norm_fact, abs_val_fx, exp_abs_val ); + IF( EQ_16( res_1, negate( 1 ) ) ) + { + norm_fact_fx = abs_val_fx; + exp_norm_fact = exp_abs_val; + } + } + } + + Word16 flag = BASOP_Util_Cmp_Mant32Exp( norm_fact_fx, exp_norm_fact, EPSILON_FX, 0 ); + IF( EQ_16( flag, negate( 1 ) ) ) + { + norm_fact_fx = ONE_IN_Q30; + exp_norm_fact = 1; + } + + Word16 exp_tmp = 0; + Word16 tmp = BASOP_Util_Divide3232_Scale( PCM16_TO_FLT_FAC_FX_Q15, norm_fact_fx, &exp_tmp ); + exp_tmp = add( exp_tmp, sub( 16, exp_norm_fact ) ); + norm_fact_fx = L_deposit_h( tmp ); + exp_norm_fact = exp_tmp; + + *exp_norm_fact_fx = exp_norm_fact; + + return norm_fact_fx; +} + +static void isar_split_rend_huffman_encode( + isar_split_rend_huffman_cfg_t *huff_cfg, + const Word16 in, + Word32 *hcode, + Word32 *hlen ) +{ + Word32 min_sym_val; + const Word32 *codebook; + + min_sym_val = huff_cfg->codebook[0]; + move32(); + + codebook = &huff_cfg->codebook[3 * ( in - min_sym_val )]; + *hlen = codebook[1]; + move32(); + *hcode = codebook[2]; + move32(); + + return; +} + +static void isar_split_rend_quant_md_fx( + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd, + const ISAR_SPLIT_REND_POSE_TYPE pose_type, + const int16_t real_only, + Word32 fix_pos_rot_mat[][BINAURAL_CHANNELS], + const Word32 pred_1byquantstep, // Q26 + const Word16 Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + float fix_pos_rot_mat_flt[][BINAURAL_CHANNELS], + const float pred_1byquantstep_flt // Q26 +#endif +) +{ + int16_t ch1, ch2; + int16_t gd_idx_min; +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word32 quant_val; +#else + Word32 sign, quant_val; +#endif +#ifdef DEBUG_QUANT_MD_FX + float quant_val_flt; + Word16 tmp; +#endif + if ( pose_type == PRED_ONLY || pose_type == PRED_ROLL_ONLY ) + { + Word32 onebyquantstep; + + onebyquantstep = pred_1byquantstep; +#ifdef DEBUG_QUANT_MD_FX + float onebyquantstep_flt = pred_1byquantstep_flt; +#endif + IF( real_only == 1 ) + { +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + hMd->pred_mat_re_fx[ch1][ch1] = hMd->pred_mat_re2[ch1]; + } + hMd->pred_mat_re_fx[1][0] = 0; + hMd->pred_mat_re_fx[0][1] = 0; + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + quant_val = L_sub( hMd->pred_mat_re_fx[ch1][ch2], L_shr_r( ( ch1 == ch2 ) ? ONE_IN_Q31 : 0, sub( Q31, Q_frame ) ) ); + quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PRED_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( quant_val, L_shr_r( ISAR_SPLIT_REND_PRED_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); + hMd->pred_mat_re_idx[ch1][ch2] = (Word16) L_shr_r( Mpy_32_32( onebyquantstep, quant_val ), sub( Q_frame, 5 ) ); // Q25*Q26 = Q20 -> Q16 -> Q0 + } + } +#else + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sign = GE_32( hMd->pred_mat_re_fx[ch1][ch2], 0 ) ? 1 : -1; + Word16 exp_out; + ivas_calculate_abs_fx( hMd->pred_mat_re_fx[ch1][ch2], Q31 - Q_frame, hMd->pred_mat_im_fx[ch1][ch2], Q31 - Q_frame, &hMd->pred_mat_re_fx[ch1][ch2], &exp_out ); + hMd->pred_mat_re_fx[ch1][ch2] = L_shr_r( hMd->pred_mat_re_fx[ch1][ch2], sub( sub( Q31, Q_frame ), exp_out ) ); // Q_frame + hMd->pred_mat_re_fx[ch1][ch2] = (Word32) W_mult0_32_32( hMd->pred_mat_re_fx[ch1][ch2], sign ); + hMd->pred_mat_im_fx[ch1][ch2] = 0; + } + } +#endif + } +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + else + { +#endif + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + quant_val = L_sub( hMd->pred_mat_re_fx[ch1][ch2], L_shr_r( fix_pos_rot_mat[ch1][ch2], sub( Q31, Q_frame ) ) ); + quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PRED_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( quant_val, L_shr_r( ISAR_SPLIT_REND_PRED_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); + hMd->pred_mat_re_idx[ch1][ch2] = (Word16) L_shr_r( Mpy_32_32( onebyquantstep, quant_val ), sub( Q_frame, 5 ) ); // Q25*Q26 = Q20 -> Q16 -> Q0 + +#ifdef DEBUG_QUANT_MD_FX + quant_val_flt = hMd->pred_mat_re[ch1][ch2] - fix_pos_rot_mat_flt[ch1][ch2]; + quant_val_flt = min( ISAR_SPLIT_REND_PRED_MAX_VAL, max( quant_val_flt, ISAR_SPLIT_REND_PRED_MIN_VAL ) ); + tmp = (int16_t) roundf( onebyquantstep_flt * quant_val_flt ); + if ( hMd->pred_mat_re_idx[ch1][ch2] != tmp ) + { + printf( "\nUNEQUAL INDEX\n" ); + } +#endif + } + } +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + } +#endif + + if ( real_only == 0 ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PRED_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( hMd->pred_mat_im_fx[ch1][ch2], L_shr_r( ISAR_SPLIT_REND_PRED_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); + hMd->pred_mat_im_idx[ch1][ch2] = (Word16) L_shr_r( Mpy_32_32( onebyquantstep, quant_val ), sub( Q_frame, 5 ) ); + // hMd->pred_mat_im[ch1][ch2] = hMd->pred_mat_im_idx[ch1][ch2] * IVAS_SPLIT_REND_PRED_Q_STEP; + + +#ifdef DEBUG_QUANT_MD_FX + quant_val_flt = min( ISAR_SPLIT_REND_PRED_MAX_VAL, max( hMd->pred_mat_im[ch1][ch2], ISAR_SPLIT_REND_PRED_MIN_VAL ) ); + tmp = (int16_t) roundf( onebyquantstep_flt * quant_val_flt ); + if ( hMd->pred_mat_im_idx[ch1][ch2] != tmp ) + { + printf( "\nUNEQUAL INDEX\n" ); + } +#endif + } + } + } + } + else if ( pose_type == COM_GAIN_ONLY ) + { + quant_val = L_min( L_shl_r( 1, Q_frame ) /*ISAR_SPLIT_REND_D_MAX_VAL_FX*/, L_max( hMd->gd_fx, ISAR_SPLIT_REND_D_MIN_VAL_FX ) ); //_frame + gd_idx_min = 0; //(int16_t)roundf(ISAR_SPLIT_REND_D_1BYQ_STEP * ISAR_SPLIT_REND_D_MIN_VAL) + hMd->gd_idx = (Word16) L_shr_r( Mpy_32_32( ISAR_SPLIT_REND_D_1BYQ_STEP_Q27, quant_val ), sub( Q_frame, 4 ) ); + hMd->gd_fx = W_extract_l( W_shr( W_mult0_32_32( hMd->gd_idx, ISAR_SPLIT_REND_D_Q_STEP_Q31 ), sub( Q31, Q_frame ) ) ); + hMd->gd_idx = sub( hMd->gd_idx, gd_idx_min ); + +#ifdef DEBUG_QUANT_MD_FX + quant_val_flt = min( ISAR_SPLIT_REND_D_MAX_VAL, max( hMd->gd, ISAR_SPLIT_REND_D_MIN_VAL ) ); + gd_idx_min = (int16_t) roundf( ISAR_SPLIT_REND_D_1BYQ_STEP * ISAR_SPLIT_REND_D_MIN_VAL ); + tmp = (int16_t) roundf( ISAR_SPLIT_REND_D_1BYQ_STEP * quant_val_flt ); + tmp = tmp - gd_idx_min; + if ( hMd->gd_idx != tmp ) + { + printf( "\nUNEQUAL INDEX\n" ); + } +#endif + } + else if ( pose_type == LR_GAIN_ONLY ) + { + quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PITCH_G_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( L_add( hMd->gd_fx, shr( 20, sub( Q30, Q_frame ) ) ), L_shr_r( ISAR_SPLIT_REND_PITCH_G_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); // Q25 + gd_idx_min = 7; // (int16_t)roundf(ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * ISAR_SPLIT_REND_PRED_MAX_VAL) + hMd->gd_idx = (Word16) L_shr_r( Mpy_32_32( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP_Q27, quant_val ), sub( Q_frame, 4 ) ); + hMd->gd_idx = sub( hMd->gd_idx, gd_idx_min ); + +#ifdef DEBUG_QUANT_MD_FX + quant_val_flt = min( ISAR_SPLIT_REND_PITCH_G_MAX_VAL, max( hMd->gd, ISAR_SPLIT_REND_PRED_MAX_VAL ) ); + gd_idx_min = (int16_t) roundf( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * ISAR_SPLIT_REND_PRED_MAX_VAL ); + tmp = (int16_t) roundf( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * quant_val_flt ); + tmp = tmp - gd_idx_min; + if ( hMd->gd_idx != tmp ) + { + printf( "\nUNEQUAL INDEX\n" ); + } +#endif + quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PITCH_G_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( L_add( hMd->gd2_fx, shr( 20, sub( Q30, Q_frame ) ) ), L_shr_r( ISAR_SPLIT_REND_PITCH_G_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); // Q25 + hMd->gd2_idx = (Word16) L_shr_r( Mpy_32_32( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP_Q27, quant_val ), sub( Q_frame, 4 ) ); + hMd->gd2_idx = sub( hMd->gd2_idx, gd_idx_min ); + +#ifdef DEBUG_QUANT_MD_FX + quant_val_flt = min( ISAR_SPLIT_REND_PITCH_G_MAX_VAL, max( hMd->gd2, ISAR_SPLIT_REND_PRED_MAX_VAL ) ); + tmp = (int16_t) roundf( ISAR_SPLIT_REND_PITCH_G_1BYQ_STEP * quant_val_flt ); + tmp = tmp - gd_idx_min; + if ( hMd->gd2_idx != tmp ) + { + printf( "\nUNEQUAL INDEX\n" ); + } +#endif + } + return; +} + + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS +static void get_lr_gains( Word32 cov_ii_re_fx[][BINAURAL_CHANNELS], + const Word16 exp_cov_ii_re, + Word32 cov_oo_re_fx[][BINAURAL_CHANNELS], + const Word16 exp_cov_oo_re, + Word32 gains_fx[BINAURAL_CHANNELS], + Word16 *exp_gains_fx ) +{ + Word16 exp_gd_tmp_buf[BINAURAL_CHANNELS] = { 0 }; + Word16 exp_gd_tmp = 0, i; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + gains_fx[i] = cov_ii_re_fx[i][i]; + move32(); + exp_gd_tmp_buf[i] = exp_cov_ii_re; + move16(); + + Word16 flag = BASOP_Util_Cmp_Mant32Exp( gains_fx[i], exp_gd_tmp_buf[i], EPSILON_FX, 0 ); + IF( EQ_16( flag, negate( 1 ) ) ) + { + gains_fx[i] = ONE_IN_Q25; + move32(); + exp_gd_tmp_buf[i] = 6; + move16(); + } + ELSE + { + Word16 tmp, tmp_sqrt, exp_tmp = 0; + tmp = BASOP_Util_Divide3232_Scale( cov_oo_re_fx[i][i], gains_fx[i], &exp_tmp ); + exp_tmp = exp_tmp + ( exp_cov_oo_re - exp_gd_tmp_buf[i] ); + tmp_sqrt = Sqrt16( tmp, &exp_tmp ); + gains_fx[i] = L_deposit_h( tmp_sqrt ); + move32(); + exp_gd_tmp_buf[i] = exp_tmp; + move16(); + } + } + + Word16 max_gd_exp = MIN16B; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + max_gd_exp = max( max_gd_exp, exp_gd_tmp_buf[i] ); + } + exp_gd_tmp = max_gd_exp; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + gains_fx[i] = L_shr( gains_fx[i], max_gd_exp - exp_gd_tmp_buf[i] ); + move32(); + } + + *exp_gains_fx = exp_gd_tmp; + move16(); + return; +} +#endif + +static void ComputeCoeffs_fx( + Word32 cov_ii_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_re, + Word32 cov_ii_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_ii_im, + Word32 cov_io_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_io_re, + Word32 cov_io_im_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_io_im, + Word32 cov_oo_re_fx[][BINAURAL_CHANNELS], + Word16 exp_cov_oo_re, + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd, + const ISAR_SPLIT_REND_POSE_TYPE pose_type, + const Word16 real_only ) +{ + Word16 i, j; + Word32 gd_fx, gl2_fx, gr2_fx, cov_norm_fact_fx; + Word16 exp_gd = 0; + + Word32 postpred_cov_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 exp_postpred_cov_re = 0; + + Word32 cov_ii_norm_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 cov_ii_norm_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 cov_io_norm_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 cov_io_norm_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 cov_oo_norm_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + + Word16 exp_cov_ii_norm_re = 0, exp_cov_ii_norm_im = 0, exp_cov_io_norm_re = 0, exp_cov_io_norm_im = 0, exp_cov_oo_norm_re = 0; + Word16 exp_pred_re = 0, exp_pred_im = 0; + + IF( EQ_16( pose_type, PITCH_ONLY ) ) + { + Word32 gd_tmp_fx[BINAURAL_CHANNELS]; + Word16 exp_gd_tmp_buf[BINAURAL_CHANNELS] = { 0 }; + Word16 exp_gd_tmp = 0; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + gd_tmp_fx[i] = cov_ii_re_fx[i][i]; + move32(); + exp_gd_tmp_buf[i] = exp_cov_ii_re; + move16(); + exp_gd_tmp = exp_cov_ii_re; + + Word16 flag = BASOP_Util_Cmp_Mant32Exp( gd_tmp_fx[i], exp_gd_tmp, EPSILON_FX, 0 ); + IF( EQ_16( flag, negate( 1 ) ) ) + { + gd_tmp_fx[i] = ONE_IN_Q25; + move32(); + exp_gd_tmp_buf[i] = 6; + move16(); + } + ELSE + { + Word16 tmp, tmp_sqrt, exp_tmp = 0; + tmp = BASOP_Util_Divide3232_Scale( cov_oo_re_fx[i][i], gd_tmp_fx[i], &exp_tmp ); + exp_tmp = add( exp_tmp, sub( exp_cov_oo_re, exp_gd_tmp ) ); + tmp_sqrt = Sqrt16( tmp, &exp_tmp ); + gd_tmp_fx[i] = L_deposit_h( tmp_sqrt ); + move32(); + exp_gd_tmp_buf[i] = exp_tmp; + move16(); + } + } + + Word16 max_gd_exp = MIN16B; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + max_gd_exp = s_max( max_gd_exp, exp_gd_tmp_buf[i] ); + } + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + gd_tmp_fx[i] = L_shr( gd_tmp_fx[i], max_gd_exp - exp_gd_tmp_buf[i] ); + move32(); + } + exp_gd_tmp = max_gd_exp; + move16(); + hMd->gd_fx = gd_tmp_fx[0]; + move16(); + hMd->gd2_fx = gd_tmp_fx[1]; + move16(); + hMd->exp_gd = exp_gd_tmp; + move16(); + hMd->exp_gd2 = exp_gd_tmp; + move16(); + } + ELSE + { + IF( real_only ) + { +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word32 gd_tmp_fx[BINAURAL_CHANNELS]; + get_lr_gains( cov_ii_re_fx, exp_cov_ii_re, + cov_oo_re_fx, exp_cov_oo_re, + gd_tmp_fx, &hMd->exp_pred_mat_re2 ); + hMd->pred_mat_re_fx[1][0] = 0; + move32(); + hMd->pred_mat_re_fx[0][1] = 0; + move32(); + hMd->exp_pred_mat_re = hMd->exp_pred_mat_re2; + move16(); + hMd->exp_pred_mat_im = hMd->exp_pred_mat_re; + move16(); + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + hMd->pred_mat_re_fx[i][i] = gd_tmp_fx[i]; + hMd->pred_mat_re2[i] = gd_tmp_fx[i]; + set32_fx( hMd->pred_mat_im_fx[i], 0, BINAURAL_CHANNELS ); + } + + +#else + Word32 gd_tmp_fx[BINAURAL_CHANNELS]; + Word16 exp_gd_tmp_buf[BINAURAL_CHANNELS] = { 0 }; + Word16 exp_gd_tmp = 0; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + gd_tmp_fx[i] = cov_ii_re_fx[i][i]; + move32(); + exp_gd_tmp_buf[i] = exp_cov_ii_re; + move16(); + + Word16 flag = BASOP_Util_Cmp_Mant32Exp( gd_tmp_fx[i], exp_gd_tmp_buf[i], EPSILON_FX, 0 ); + IF( EQ_16( flag, negate( 1 ) ) ) + { + gd_tmp_fx[i] = ONE_IN_Q25; + move32(); + exp_gd_tmp_buf[i] = 6; + move16(); + } + ELSE + { + Word16 tmp, tmp_sqrt, exp_tmp = 0; + tmp = BASOP_Util_Divide3232_Scale( cov_oo_re_fx[i][i], gd_tmp_fx[i], &exp_tmp ); + exp_tmp = exp_tmp + ( exp_cov_oo_re - exp_gd_tmp_buf[i] ); + tmp_sqrt = Sqrt16( tmp, &exp_tmp ); + gd_tmp_fx[i] = L_deposit_h( tmp_sqrt ); + move32(); + exp_gd_tmp_buf[i] = exp_tmp; + move16(); + } + hMd->pred_mat_re_fx[i][i] = gd_tmp_fx[i]; + move32(); + set32_fx( hMd->pred_mat_im_fx[i], 0, BINAURAL_CHANNELS ); + } + hMd->pred_mat_re_fx[1][0] = 0; + move32(); + hMd->pred_mat_re_fx[0][1] = 0; + move32(); + + Word16 max_gd_exp = MIN16B; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + max_gd_exp = max( max_gd_exp, exp_gd_tmp_buf[i] ); + } + exp_gd_tmp = max_gd_exp; + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + hMd->pred_mat_re_fx[i][i] = L_shr( hMd->pred_mat_re_fx[i][i], max_gd_exp - exp_gd_tmp_buf[i] ); + move32(); + } + + exp_pred_re = exp_gd_tmp; + move16(); + exp_pred_im = exp_gd_tmp; + move16(); + + hMd->exp_pred_mat_re = exp_pred_re; + move16(); + hMd->exp_pred_mat_im = exp_pred_im; + move16(); +#endif + } + ELSE + { +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + get_lr_gains( cov_ii_re_fx, exp_cov_ii_re, + cov_oo_re_fx, exp_cov_oo_re, + hMd->pred_mat_re2, &hMd->exp_pred_mat_re2 ); +#endif + Word16 exp_norm_fact = 0; + cov_norm_fact_fx = GetNormFact_fx( cov_ii_re_fx, exp_cov_ii_re, cov_ii_im_fx, exp_cov_ii_im, cov_io_re_fx, exp_cov_io_re, cov_io_im_fx, exp_cov_io_im, cov_oo_re_fx, exp_cov_oo_re, &exp_norm_fact ); + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + cov_ii_norm_re_fx[i][j] = Mpy_32_32( cov_ii_re_fx[i][j], cov_norm_fact_fx ); + move32(); + cov_ii_norm_im_fx[i][j] = Mpy_32_32( cov_ii_im_fx[i][j], cov_norm_fact_fx ); + move32(); + cov_io_norm_re_fx[i][j] = Mpy_32_32( cov_io_re_fx[i][j], cov_norm_fact_fx ); + move32(); + cov_io_norm_im_fx[i][j] = Mpy_32_32( cov_io_im_fx[i][j], cov_norm_fact_fx ); + move32(); + cov_oo_norm_re_fx[i][j] = Mpy_32_32( cov_oo_re_fx[i][j], cov_norm_fact_fx ); + move32(); + } + } + + exp_cov_ii_norm_re = add( exp_cov_ii_re, exp_norm_fact ); + exp_cov_ii_norm_im = add( exp_cov_ii_im, exp_norm_fact ); + exp_cov_io_norm_re = add( exp_cov_io_re, exp_norm_fact ); + exp_cov_io_norm_im = add( exp_cov_io_im, exp_norm_fact ); + exp_cov_oo_norm_re = add( exp_cov_oo_re, exp_norm_fact ); + + ComputePredMat_fx( cov_ii_norm_re_fx, exp_cov_ii_norm_re, cov_ii_norm_im_fx, exp_cov_ii_norm_im, cov_io_norm_re_fx, exp_cov_io_norm_re, cov_io_norm_im_fx, exp_cov_io_norm_im, hMd->pred_mat_re_fx, &exp_pred_re, hMd->pred_mat_im_fx, &exp_pred_im, BINAURAL_CHANNELS, real_only ); + hMd->exp_pred_mat_re = exp_pred_re; + move16(); + hMd->exp_pred_mat_im = exp_pred_im; + move16(); + + /*TODO : change this function to real only as thats what is needed*/ + ComputePostPredCov_fx( cov_ii_norm_re_fx, exp_cov_ii_norm_re, cov_ii_norm_im_fx, exp_cov_ii_norm_im, hMd->pred_mat_re_fx, exp_pred_re, hMd->pred_mat_im_fx, exp_pred_im, postpred_cov_re_fx, &exp_postpred_cov_re, BINAURAL_CHANNELS ); + + /* normalize everything to +-1 range */ + Word16 gd_16_fx = BASOP_Util_Divide3232_Scale( ONE_IN_Q30, PCM16_TO_FLT_FAC_FX_Q15, &exp_gd ); + gd_fx = L_deposit_h( gd_16_fx ); + exp_gd = add( exp_gd, sub( 1, 16 ) ); + + Word16 tmp_buff_2[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmp_buff_3[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + Word64 tmp_2 = W_mult_32_32( cov_ii_norm_re_fx[i][j], gd_fx ); + Word64 tmp_3 = W_mult_32_32( cov_oo_norm_re_fx[i][j], gd_fx ); + Word16 shift_2 = W_norm( tmp_2 ); + Word16 shift_3 = W_norm( tmp_3 ); + + postpred_cov_re_fx[i][j] = Mpy_32_32( postpred_cov_re_fx[i][j], gd_fx ); + move32(); + cov_ii_norm_re_fx[i][j] = W_extract_h( W_shl( tmp_2, shift_2 ) ); + move32(); + cov_oo_norm_re_fx[i][j] = W_extract_h( W_shl( tmp_3, shift_3 ) ); + move32(); + + tmp_buff_2[i][j] = exp_cov_ii_norm_re + exp_gd - shift_2; + move16(); + tmp_buff_3[i][j] = exp_cov_oo_norm_re + exp_gd - shift_3; + move16(); + } + } + Word16 max_2 = MIN16B, max_3 = MIN16B; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + max_2 = s_max( max_2, tmp_buff_2[i][j] ); + max_3 = s_max( max_3, tmp_buff_3[i][j] ); + } + } + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + cov_ii_norm_re_fx[i][j] = L_shr( cov_ii_norm_re_fx[i][j], max_2 - tmp_buff_2[i][j] ); + move32(); + cov_oo_norm_re_fx[i][j] = L_shr( cov_oo_norm_re_fx[i][j], max_3 - tmp_buff_3[i][j] ); + move32(); + } + } + + exp_postpred_cov_re = add( exp_postpred_cov_re, exp_gd ); + exp_cov_ii_norm_re = max_2; + move16(); + exp_cov_oo_norm_re = max_3; + move16(); + + hMd->gd_fx = 0; + move16(); + Word16 exp_gl2 = 0; + move16(); + Word16 check_postPred = BASOP_Util_Cmp_Mant32Exp( postpred_cov_re_fx[0][0], exp_postpred_cov_re, EPSILON_FX, 0 ); + IF( EQ_16( check_postPred, 1 ) ) + { + Word16 exp_div_res = 0; + Word16 div_res = BASOP_Util_Divide3232_Scale( cov_oo_norm_re_fx[0][0], postpred_cov_re_fx[0][0], &exp_div_res ); + exp_div_res = exp_div_res + ( exp_cov_oo_norm_re - exp_postpred_cov_re ); + gl2_fx = L_deposit_h( div_res ); + exp_gl2 = exp_div_res; + move16(); + + Word16 Cmp1 = BASOP_Util_Cmp_Mant32Exp( gl2_fx, exp_gl2, ONE_IN_Q30, 1 ); + IF( EQ_16( Cmp1, negate( 1 ) ) ) + { + gl2_fx = ONE_IN_Q30; + exp_gl2 = 1; + move16(); + move16(); + } + + gl2_fx = Sqrt32( gl2_fx, &exp_gl2 ); + } + ELSE + { + gl2_fx = ONE_IN_Q30; + exp_gl2 = 1; + move16(); + move16(); + } + + Word16 exp_gr2 = 0; + check_postPred = BASOP_Util_Cmp_Mant32Exp( postpred_cov_re_fx[1][1], exp_postpred_cov_re, EPSILON_FX, 0 ); + IF( EQ_16( check_postPred, 1 ) ) + { + Word16 exp_div_res = 0; + Word16 div_res = BASOP_Util_Divide3232_Scale( cov_oo_norm_re_fx[1][1], postpred_cov_re_fx[1][1], &exp_div_res ); + exp_div_res = exp_div_res + ( exp_cov_oo_norm_re - exp_postpred_cov_re ); + gr2_fx = L_deposit_h( div_res ); + exp_gr2 = exp_div_res; + + Word16 Cmp1 = BASOP_Util_Cmp_Mant32Exp( gr2_fx, exp_gr2, ONE_IN_Q30, 1 ); + IF( EQ_16( Cmp1, negate( 1 ) ) ) + { + gr2_fx = ONE_IN_Q30; + move16(); + exp_gr2 = 1; + move16(); + } + + gr2_fx = Sqrt32( gr2_fx, &exp_gr2 ); + } + ELSE + { + gr2_fx = ONE_IN_Q30; + move16(); + exp_gr2 = 1; + move16(); + } + + Word16 pred_mat_buf_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 pred_mat_buf_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + pred_mat_buf_re[i][j] = exp_pred_re; + move16(); + pred_mat_buf_im[i][j] = exp_pred_im; + move16(); + } + } + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + hMd->pred_mat_re_fx[i][0] = Mpy_32_32( hMd->pred_mat_re_fx[i][0], gl2_fx ); + move32(); + hMd->pred_mat_re_fx[i][1] = Mpy_32_32( hMd->pred_mat_re_fx[i][1], gr2_fx ); + move32(); + pred_mat_buf_re[i][0] = add( exp_pred_re, exp_gl2 ); + move16(); + pred_mat_buf_re[i][1] = add( exp_pred_re, exp_gr2 ); + move16(); + } + + IF( EQ_16( real_only, 0 ) ) + { + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + hMd->pred_mat_im_fx[i][0] = Mpy_32_32( hMd->pred_mat_im_fx[i][0], gl2_fx ); + move32(); + hMd->pred_mat_im_fx[i][1] = Mpy_32_32( hMd->pred_mat_im_fx[i][1], gr2_fx ); + move32(); + + pred_mat_buf_im[i][0] = add( exp_pred_im, exp_gl2 ); + move16(); + pred_mat_buf_im[i][1] = add( exp_pred_im, exp_gr2 ); + move16(); + } + } + + Word16 max_exp_pred_re = MIN16B, max_exp_pred_im = MIN16B; + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + max_exp_pred_re = s_max( max_exp_pred_re, pred_mat_buf_re[i][j] ); + max_exp_pred_im = s_max( max_exp_pred_im, pred_mat_buf_im[i][j] ); + } + } + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hMd->pred_mat_re_fx[i][j] = L_shr( hMd->pred_mat_re_fx[i][j], max_exp_pred_re - pred_mat_buf_re[i][j] ); + move32(); + hMd->pred_mat_im_fx[i][j] = L_shr( hMd->pred_mat_im_fx[i][j], max_exp_pred_im - pred_mat_buf_im[i][j] ); + move32(); + } + } + + hMd->exp_pred_mat_re = max_exp_pred_re; + move16(); + hMd->exp_pred_mat_im = max_exp_pred_im; + move16(); + } + } + + return; +} + +static void get_base2_bits( + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word16 num_subframes, + const Word16 num_quant_strats, + const Word16 pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + const Word16 pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + const Word16 d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + const Word16 bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + const Word16 pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + const Word16 pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word32 base2bits[ISAR_SPLIT_REND_NUM_QUANT_STRATS] ) +{ + Word16 pred_roll_bits; + Word16 d_gain_bits, pitch_gain_bits, pose_idx, q; + Word16 pred_yaw_bits[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word16 bin_ch_2, bin_ch_2_num_sf, bin_ch_num_sf; + + ISAR_SPLIT_REND_POSE_TYPE pose_type; + + FOR( q = 0; q < num_quant_strats; q++ ) + { + pred_yaw_bits[q] = ceil_log_2( pred_quant_pnts_yaw[q] ); + move16(); + } + pred_roll_bits = ceil_log_2( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS ); + + d_gain_bits = ceil_log_2( ISAR_SPLIT_REND_D_QUANT_PNTS ); + pitch_gain_bits = d_gain_bits; + move16(); + + FOR( q = 0; q < num_quant_strats; q++ ) + { + base2bits[q] = 0; + move32(); + } + + bin_ch_2 = DEPR_i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ); + bin_ch_2_num_sf = DEPR_i_mult( bin_ch_2, num_subframes ); + bin_ch_num_sf = DEPR_i_mult( BINAURAL_CHANNELS, num_subframes ); + + FOR( q = 0; q < num_quant_strats; q++ ) + { + FOR( pose_idx = 0; pose_idx < sub( pMultiBinPoseData->num_poses, 1 ); pose_idx++ ) + { + pose_type = hBinHrSplitPreRend->pose_type[pose_idx]; + IF( EQ_32( pose_type, ANY_YAW ) ) + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_yaw_bits[q], pred_real_bands_yaw[q] ), bin_ch_2_num_sf ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_yaw_bits[q], pred_imag_bands_yaw[q] ), bin_ch_2_num_sf ) ); + move32(); +#else + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_yaw_bits[q], pred_real_bands_yaw[q] ), bin_ch_num_sf ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_yaw_bits[q], pred_imag_bands_yaw[q] ), bin_ch_num_sf ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_yaw_bits[q], pred_imag_bands_yaw[q] ), bin_ch_2_num_sf ) ); + move32(); +#endif + + + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( d_gain_bits, d_bands_yaw[q] ), num_subframes ) ); + move32(); + } + ELSE IF( EQ_32( pose_type, PITCH_ONLY ) ) + { + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pitch_gain_bits, bands_pitch[q] ), num_subframes ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pitch_gain_bits, bands_pitch[q] ), num_subframes ) ); + move32(); + } + ELSE + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_roll_bits, pred_real_bands_roll[q] ), bin_ch_2_num_sf ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_roll_bits, pred_imag_bands_roll[q] ), bin_ch_2_num_sf ) ); + move32(); +#else + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_roll_bits, pred_real_bands_roll[q] ), bin_ch_num_sf ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_roll_bits, pred_imag_bands_roll[q] ), bin_ch_num_sf ) ); + move32(); + base2bits[q] = L_add( base2bits[q], L_mult0( DEPR_i_mult( pred_roll_bits, pred_imag_bands_roll[q] ), bin_ch_2_num_sf ) ); + move32(); +#endif + } + } + } + + return; +} + + +static void isar_SplitRenderer_code_md_base2( + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word16 num_subframes, + const Word16 pred_real_bands_yaw, + const Word16 pred_imag_bands_yaw, + const Word16 pred_quant_pnts_yaw, + const Word16 d_bands_yaw, + const Word16 bands_pitch, + const Word16 pred_real_bands_roll, + const Word16 pred_imag_bands_roll, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word16 pos_idx, b, ch1, ch2, sf_idx; + Word16 min_pred_idx, min_gd_idx, min_p_gd_idx, pred_code_len, gd_code_len, p_gd_code_len, num_poses; + Word16 min_pred_roll_idx, pred_roll_code_len; + Word16 pred_cb_idx; + Word32 code; + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd; + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg; + + pHuff_cfg = &hBinHrSplitPreRend->huff_cfg; + IF( EQ_16( pred_quant_pnts_yaw, ISAR_SPLIT_REND_PRED_63QUANT_PNTS ) ) + { + pred_cb_idx = 1; + move16(); + } + ELSE + { + pred_cb_idx = 0; + move16(); + } + min_pred_idx = extract_l( pHuff_cfg->pred[pred_cb_idx].codebook[0] ); + min_pred_roll_idx = extract_l( pHuff_cfg->pred_roll.codebook[0] ); + min_gd_idx = extract_l( pHuff_cfg->gd.codebook[0] ); + min_p_gd_idx = extract_l( pHuff_cfg->p_gd.codebook[0] ); + + pred_code_len = pHuff_cfg->pred_base2_code_len[pred_cb_idx]; + move16(); + pred_roll_code_len = pHuff_cfg->pred_roll_base2_code_len; + move16(); + gd_code_len = pHuff_cfg->gd_base2_code_len; + move16(); + p_gd_code_len = pHuff_cfg->p_gd_base2_code_len; + move16(); + + num_poses = pMultiBinPoseData->num_poses; + move16(); + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( pos_idx = 0; pos_idx < sub( num_poses, 1 ); pos_idx++ ) + { + IF( EQ_32( hBinHrSplitPreRend->pose_type[pos_idx], ANY_YAW ) ) + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_re_idx[ch1][ch2], min_pred_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len ); + } + } + } + + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_im_idx[ch1][ch2], min_pred_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len ); + } + } + } +#else + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_re_idx[ch1][ch2], min_pred_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len ); + } + } + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_im_idx[ch1][ch2], min_pred_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len ); + } + } + } + FOR( ; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + code = L_sub( hMd->pred_mat_re_idx[ch1][ch1], min_pred_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_code_len ); + } + } +#endif + FOR( b = 0; b < d_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + code = L_sub( hMd->gd_idx, min_gd_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, gd_code_len ); + } + } + ELSE IF( EQ_32( hBinHrSplitPreRend->pose_type[pos_idx], PITCH_ONLY ) ) + { + FOR( b = 0; b < bands_pitch; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + code = L_sub( hMd->gd_idx, min_p_gd_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, p_gd_code_len ); + + code = L_sub( hMd->gd2_idx, min_p_gd_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, p_gd_code_len ); + } + } + ELSE + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_re_idx[ch1][ch2], min_pred_roll_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len ); + } + } + } + + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_im_idx[ch1][ch2], min_pred_roll_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len ); + } + } + } +#else + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_re_idx[ch1][ch2], min_pred_roll_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len ); + } + } + + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + code = L_sub( hMd->pred_mat_im_idx[ch1][ch2], min_pred_roll_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len ); + } + } + } + FOR( ; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + code = L_sub( hMd->pred_mat_re_idx[ch1][ch1], min_pred_roll_idx ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, pred_roll_code_len ); + } + } +#endif + } + } + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + { + static int16_t num_bits = 0; + static int16_t cntr = 0; + float fnum_bits; + + cntr++; + + num_bits += pBits->bits_written; + /* collect bits for every second */ + if ( cntr == 50 ) + { + cntr = 0; + fnum_bits = (float) num_bits / 1000.0f; + dbgwrite_txt( &fnum_bits, 1, "split_rend_MD_bitrate.txt", "MD bitrate (kbps)" ); + num_bits = 0; + } + } +#endif + return; +} + + +static void isar_SplitRenderer_code_md_huff( + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word16 num_subframes, + const Word16 pred_real_bands_yaw, + const Word16 pred_imag_bands_yaw, + const Word16 pred_quant_pnts_yaw, + const Word16 d_bands_yaw, + const Word16 bands_pitch, + const Word16 pred_real_bands_roll, + const Word16 pred_imag_bands_roll, + ISAR_SPLIT_REND_BITS_HANDLE pBits ) +{ + Word16 pos_idx, b, ch1, ch2, sf_idx, num_poses; + Word16 sym_adj_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word16 min_pred_idx, max_pred_idx; + Word16 min_pred_roll_idx, max_pred_roll_idx, pred_cb_idx; + Word32 code, len; + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd; + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg; + + pHuff_cfg = &hBinHrSplitPreRend->huff_cfg; + + IF( EQ_16( pred_quant_pnts_yaw, ISAR_SPLIT_REND_PRED_63QUANT_PNTS ) ) + { + pred_cb_idx = 1; + move16(); + } + ELSE + { + pred_cb_idx = 0; + move16(); + } + + min_pred_idx = extract_l( pHuff_cfg->pred[pred_cb_idx].codebook[0] ); + max_pred_idx = extract_l( pHuff_cfg->pred[pred_cb_idx].codebook[DEPR_i_mult( sub( pred_quant_pnts_yaw, 1 ), 3 )] ); + min_pred_roll_idx = extract_l( pHuff_cfg->pred_roll.codebook[0] ); + max_pred_roll_idx = extract_l( pHuff_cfg->pred_roll.codebook[DEPR_i_mult( sub( ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS, 1 ), 3 )] ); + + num_poses = pMultiBinPoseData->num_poses; + move16(); + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( pos_idx = 0; pos_idx < sub( num_poses, 1 ); pos_idx++ ) + { + IF( EQ_32( hBinHrSplitPreRend->pose_type[pos_idx], ANY_YAW ) ) + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, -1, min_pred_idx, max_pred_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch2], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + } + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_im_idx, sym_adj_idx, 1, min_pred_idx, max_pred_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch2], &code, &len ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + } +#else + FOR( b = 0; b < pred_imag_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, -1, min_pred_idx, max_pred_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch2], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_im_idx, sym_adj_idx, 1, min_pred_idx, max_pred_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch2], &code, &len ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + } + FOR( ; b < pred_real_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, 1, min_pred_idx, max_pred_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred[pred_cb_idx], sym_adj_idx[ch1][ch1], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } +#endif + FOR( b = 0; b < d_bands_yaw; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_huffman_encode( &pHuff_cfg->gd, hMd->gd_idx, &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + ELSE IF( EQ_32( hBinHrSplitPreRend->pose_type[pos_idx], PITCH_ONLY ) ) + { + FOR( b = 0; b < bands_pitch; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_huffman_encode( &pHuff_cfg->p_gd, hMd->gd_idx, &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + + isar_split_rend_huffman_encode( &pHuff_cfg->p_gd, hMd->gd2_idx, &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + ELSE + { +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + FOR( b = 0; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, -1, min_pred_roll_idx, max_pred_roll_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch2], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + } + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_im_idx, sym_adj_idx, 1, min_pred_roll_idx, max_pred_roll_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch2], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + } +#else + FOR( b = 0; b < pred_imag_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, -1, min_pred_roll_idx, max_pred_roll_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch2], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_im_idx, sym_adj_idx, 1, min_pred_roll_idx, max_pred_roll_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch2], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } + } + FOR( ; b < pred_real_bands_roll; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_SplitRenderer_getdiagdiff( hMd->pred_mat_re_idx, sym_adj_idx, 1, min_pred_roll_idx, max_pred_roll_idx ); + FOR( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + isar_split_rend_huffman_encode( &pHuff_cfg->pred_roll, sym_adj_idx[ch1][ch1], &code, &len ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, code, len ); + } + } +#endif + } + } + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + { + static int16_t num_bits = 0; + static int16_t cntr = 0; + float fnum_bits; + + cntr++; + num_bits += pBits->bits_written; + /* collect bits for every second */ + IF( cntr == 50 ) + { + cntr = 0; + fnum_bits = (float) num_bits / 1000.0f; + dbgwrite_txt( &fnum_bits, 1, "split_rend_MD_bitrate.txt", "MD bitrate (kbps)" ); + num_bits = 0; + } + } +#endif + return; +} + +static void isar_SplitRenderer_quant_code( + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + const IVAS_QUATERNION headPosition, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word16 low_res_pre_rend_rot, +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + const int16_t ro_md_flag, +#endif + const Word32 target_md_bits, + Word16 Q_frame ) +{ +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word16 q, num_subframes, sf_idx, pos_idx, b, num_quant_strats; +#else + Word16 num_complex_bands, q, num_subframes, sf_idx, pos_idx, b, num_quant_strats; +#endif + Word32 overhead_bits, quant_strat_bits, huff_bits, start_bit; + Word16 pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word16 pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word16 d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word32 base2bits[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word16 pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word32 pred_1byquantstep_yaw_fx[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + Word32 pred_quantstep_yaw_fx[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; +#ifdef DEBUG_QUANT_MD_FX + float pred_1byquantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; + float pred_quantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS]; +#endif + ISAR_BIN_HR_SPLIT_REND_MD_HANDLE hMd; +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word16 rot_axis_code, num_bits; +#endif + + IF( low_res_pre_rend_rot ) + { + num_subframes = 1; + } + ELSE + { + num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + } + + overhead_bits = pBits->bits_written; + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pMultiBinPoseData->dof, ISAR_SPLIT_REND_DOF_BITS ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, pMultiBinPoseData->hq_mode, ISAR_SPLIT_REND_HQ_MODE_BITS ); +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + rot_axis_code = isar_renderSplitGetCodeFromRot_axis( pMultiBinPoseData->dof, pMultiBinPoseData->rot_axis, &num_bits ); + if ( num_bits > 0 ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, (int32_t) rot_axis_code, num_bits ); + } + ISAR_SPLIT_REND_BITStream_write_int32( pBits, (int32_t) ro_md_flag, ISAR_SPLIT_REND_RO_FLAG_BITS ); +#else + ISAR_SPLIT_REND_BITStream_write_int32( pBits, (int32_t) pMultiBinPoseData->rot_axis, ISAR_SPLIT_REND_ROT_AXIS_BITS ); +#endif + + /* code ref pose*/ + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + Word16 angle; + IVAS_QUATERNION head_pos_euler; + + Quat2EulerDegree_fx( headPosition, &head_pos_euler.z_fx, &head_pos_euler.y_fx, &head_pos_euler.x_fx ); + angle = (Word16) L_shr_r( head_pos_euler.x_fx, Q22 ); + angle = add( angle, 180 ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS ); + + angle = (Word16) L_shr_r( head_pos_euler.y_fx, Q22 ); + angle = add( angle, 180 ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS ); + + angle = (Word16) L_shr_r( head_pos_euler.z_fx, Q22 ); + angle = add( angle, 180 ); + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS ); + } + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + isar_split_rend_get_quant_params_fx( MAX_SPLIT_REND_MD_BANDS, pred_real_bands_yaw, pred_imag_bands_yaw, + pred_quant_pnts_yaw, pred_quantstep_yaw_fx, pred_1byquantstep_yaw_fx, + d_bands_yaw, bands_pitch, pred_real_bands_roll, pred_imag_bands_roll, ro_md_flag, &num_quant_strats ); +#else + isar_split_rend_get_quant_params_fx( MAX_SPLIT_REND_MD_BANDS, pred_real_bands_yaw, pred_imag_bands_yaw, + pred_quant_pnts_yaw, pred_quantstep_yaw_fx, pred_1byquantstep_yaw_fx, + d_bands_yaw, bands_pitch, pred_real_bands_roll, pred_imag_bands_roll, &num_quant_strats, &num_complex_bands ); +#endif +#ifdef DEBUG_QUANT_MD_FX + fixedToFloat_arrL( pred_quantstep_yaw_fx, pred_quantstep_yaw, Q31, ISAR_SPLIT_REND_NUM_QUANT_STRATS ); + fixedToFloat_arrL( pred_1byquantstep_yaw_fx, pred_1byquantstep_yaw, Q26, ISAR_SPLIT_REND_NUM_QUANT_STRATS ); +#endif + + quant_strat_bits = ceil_log_2( num_quant_strats ); + + overhead_bits = L_add( L_add( L_sub( pBits->bits_written, overhead_bits ), quant_strat_bits ), 1 ); /* 1 for base2 vs huff */ + + get_base2_bits( hBinHrSplitPreRend, pMultiBinPoseData, num_subframes, num_quant_strats, pred_real_bands_yaw, pred_imag_bands_yaw, + pred_quant_pnts_yaw, + d_bands_yaw, bands_pitch, pred_real_bands_roll, pred_imag_bands_roll, base2bits ); + + FOR( q = 0; q < num_quant_strats; q++ ) + { + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + IF( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_YAW ) + { + FOR( b = 0; b < pred_imag_bands_yaw[q]; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_quant_md_fx( hMd, PRED_ONLY, 0, hBinHrSplitPreRend->fix_pos_rot_mat_fx[pos_idx], pred_1byquantstep_yaw_fx[q], Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], pred_1byquantstep_yaw[q] +#endif + ); + } + FOR( ; b < pred_real_bands_yaw[q]; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_quant_md_fx( hMd, PRED_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat_fx[pos_idx], pred_1byquantstep_yaw_fx[q], Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], pred_1byquantstep_yaw[q] +#endif + ); + } + + FOR( b = 0; b < d_bands_yaw[q]; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_quant_md_fx( hMd, COM_GAIN_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat_fx[pos_idx], 0, Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], 0.0f +#endif + ); + } + } + ELSE IF( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY ) + { + FOR( b = 0; b < bands_pitch[q]; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_quant_md_fx( hMd, LR_GAIN_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat_fx[pos_idx], 0, Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], 0.0f +#endif + ); + } + } + ELSE + { + FOR( b = 0; b < pred_imag_bands_roll[q]; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_quant_md_fx( hMd, PRED_ROLL_ONLY, 0, hBinHrSplitPreRend->fix_pos_rot_mat_fx[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP_Q26, Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP +#endif + ); + } + FOR( ; b < pred_real_bands_roll[q]; b++ ) + { + hMd = &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + isar_split_rend_quant_md_fx( hMd, PRED_ROLL_ONLY, 1, hBinHrSplitPreRend->fix_pos_rot_mat_fx[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP_Q26, Q_frame +#ifdef DEBUG_QUANT_MD_FX + , + hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx], ISAR_SPLIT_REND_PRED_ROLL_1BYQ_STEP +#endif + ); + } + } + } + } + + /*get base2 bits and check if its within target. if yes then code with base2 to save complexity on post renderer*/ + start_bit = pBits->bits_written; + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 1, 1 ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, q, quant_strat_bits ); + + huff_bits = pBits->bits_written; + isar_SplitRenderer_code_md_huff( + hBinHrSplitPreRend, + pMultiBinPoseData, + num_subframes, + pred_real_bands_yaw[q], + pred_imag_bands_yaw[q], + pred_quant_pnts_yaw[q], + d_bands_yaw[q], + bands_pitch[q], + pred_real_bands_roll[q], + pred_imag_bands_roll[q], + pBits ); + + huff_bits = L_sub( pBits->bits_written, huff_bits ); + test(); + test(); + test(); + IF( GE_32( target_md_bits, ( base2bits[q] + overhead_bits ) ) || GE_32( target_md_bits, ( huff_bits + overhead_bits ) ) || EQ_16( q, sub( num_quant_strats, 1 ) ) ) + { + IF( GT_32( huff_bits, base2bits[q] ) ) + { + pBits->bits_written = start_bit; + + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0, 1 ); + ISAR_SPLIT_REND_BITStream_write_int32( pBits, q, quant_strat_bits ); + + isar_SplitRenderer_code_md_base2( hBinHrSplitPreRend, pMultiBinPoseData, num_subframes, pred_real_bands_yaw[q], pred_imag_bands_yaw[q], + pred_quant_pnts_yaw[q], + d_bands_yaw[q], bands_pitch[q], pred_real_bands_roll[q], pred_imag_bands_roll[q], pBits ); + } + BREAK; + } + + pBits->bits_written = start_bit; + } + +#ifdef SPLIT_MD_CODING_DEBUG + for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + int16_t val, quant_strat, ch1, ch2; + char filename[200] = "split_md_debug_indices.bin"; + quant_strat = q; + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + if ( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_YAW ) + { + for ( b = 0; b < pred_real_bands_yaw[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2]; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + } + } + } + for ( b = 0; b < pred_imag_bands_yaw[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2]; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + } + } + } + for ( b = 0; b < d_bands_yaw[quant_strat]; b++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_idx; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + } + } + else if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY ) + { + for ( b = 0; b < bands_pitch[quant_strat]; b++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_idx; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_idx; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + } + } + else + { + for ( b = 0; b < pred_real_bands_roll[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_idx[ch1][ch2]; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + } + } + } + for ( b = 0; b < pred_imag_bands_roll[quant_strat]; b++ ) + { + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + val = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_idx[ch1][ch2]; + dbgwrite( &val, sizeof( int16_t ), 1, 1, filename ); + } + } + } + } + } + } +#endif + + return; +} +/*------------------------------------------------------------------------- + * Function isar_SplitRenderer_GetRotMd() + * + * + *------------------------------------------------------------------------*/ + +static Word16 imult1616( Word16 x, Word16 y ) +{ + assert( (int) x * (int) y < 32768 && (int) x * (int) y >= -32768 ); + return extract_l( L_mult0( x, y ) ); +} + +static void isar_SplitRenderer_GetRotMd_fx( + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i/o: binaural renderer handle */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_RealBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ + Word16 exp_cldfb_re, + Word32 Cldfb_ImagBuffer_Ref_Binaural_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Reference Binaural signals */ + Word16 exp_cldfb_im, + const Word16 low_res, + const Word16 ro_md_flag ) +{ + Word32 cov_ii_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { 0 }; + Word32 cov_oo_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { 0 }; + Word32 cov_io_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { 0 }; + Word32 cov_ii_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { 0 }; + Word32 cov_oo_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { 0 }; + Word32 cov_io_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { 0 }; + Word16 exp_cov_io_re = 0, exp_cov_io_im = 0; + Word16 exp_cov_ii_re = 0, exp_cov_ii_im = 0; + Word16 exp_cov_oo_re = 0, exp_cov_oo_im = 0; + + Word16 real_only = 0; + Word16 pos_idx, b, sf_idx, start_slot_idx, num_slots, num_subframes, ch_s_idx1, ch_s_idx2; + Word16 num_md_bands, num_poses; + const Word16 *pBand_grouping = isar_split_rend_band_grouping; + + push_wmops( "isar_SplitRenderer_GetRotMd_fx" ); + + num_md_bands = MAX_SPLIT_REND_MD_BANDS; + move16(); + num_poses = pMultiBinPoseData->num_poses; + move16(); + + IF( low_res ) + { + num_slots = CLDFB_NO_COL_MAX; + move16(); + num_subframes = 1; + move16(); + } + ELSE + { + num_slots = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + } + + /* compute reference signal covariance */ + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + start_slot_idx = imult1616( sf_idx, num_slots ); + FOR( b = 0; b < num_md_bands; b++ ) + { + test(); + IF( LT_16( b, SPLIT_REND_RO_MD_BAND_THRESH ) || ( !ro_md_flag && b < COMPLEX_MD_BAND_THRESH ) ) + { + real_only = 0; + move16(); + } + ELSE + { + real_only = 1; + move16(); + } + + ch_s_idx1 = 0; + + ComputeBandedCov_fx( Cldfb_RealBuffer_Ref_Binaural_fx, exp_cldfb_re, Cldfb_ImagBuffer_Ref_Binaural_fx, exp_cldfb_im, ch_s_idx1, cov_ii_re_fx, &exp_cov_ii_re, cov_ii_im_fx, &exp_cov_ii_im, BINAURAL_CHANNELS, pBand_grouping, num_slots, start_slot_idx, b, real_only ); + + /* compute rotated signal covariance */ + FOR( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ ) + { + IF( hBinHrSplitPreRend->pose_type[pos_idx] == ANY_ROLL ) + { + IF( GE_16( b, SPLIT_REND_RO_MD_BAND_THRESH ) ) + { + real_only = 1; + } + } + ch_s_idx2 = imult1616( add( pos_idx, 1 ), BINAURAL_CHANNELS ); + + ComputeBandedCrossCov_fx( Cldfb_RealBuffer_Ref_Binaural_fx, exp_cldfb_re, Cldfb_ImagBuffer_Ref_Binaural_fx, exp_cldfb_im, ch_s_idx1, Cldfb_RealBuffer_Ref_Binaural_fx, exp_cldfb_re, Cldfb_ImagBuffer_Ref_Binaural_fx, exp_cldfb_im, ch_s_idx2, cov_io_re_fx, &exp_cov_io_re, cov_io_im_fx, &exp_cov_io_im, BINAURAL_CHANNELS, pBand_grouping, num_slots, start_slot_idx, b, real_only ); + + ComputeBandedCov_fx( Cldfb_RealBuffer_Ref_Binaural_fx, exp_cldfb_re, Cldfb_ImagBuffer_Ref_Binaural_fx, exp_cldfb_im, ch_s_idx2, cov_oo_re_fx, &exp_cov_oo_re, cov_oo_im_fx, &exp_cov_oo_im, BINAURAL_CHANNELS, pBand_grouping, num_slots, start_slot_idx, b, real_only ); + + ComputeCoeffs_fx( cov_ii_re_fx, exp_cov_ii_re, cov_ii_im_fx, exp_cov_ii_im, cov_io_re_fx, exp_cov_io_re, cov_io_im_fx, exp_cov_io_im, cov_oo_re_fx, exp_cov_oo_re, &hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b], hBinHrSplitPreRend->pose_type[pos_idx], real_only ); + } + } + } + + pop_wmops(); + return; +} +/*------------------------------------------------------------------------- + * Function isar_rend_CldfbSplitPreRendProcess() + * + * + *------------------------------------------------------------------------*/ +void isar_rend_CldfbSplitPreRendProcess( + const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, + const IVAS_QUATERNION headPosition, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_re, + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 exp_cldfb_im, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 target_md_bits, + const Word16 low_res_pre_rend_rot, + const Word16 ro_md_flag ) +{ + push_wmops( "isar_rend_CldfbSplitPreRendProcess" ); + + isar_SplitRenderer_GetRotMd_fx( hBinHrSplitPreRend, pMultiBinPoseData, Cldfb_In_BinReal_fx, exp_cldfb_re, Cldfb_In_BinImag_fx, exp_cldfb_im, low_res_pre_rend_rot, ro_md_flag ); + + Word16 num_md_bands, num_poses; + Word16 pos_idx, b, sf_idx, num_subframes; + + num_md_bands = MAX_SPLIT_REND_MD_BANDS; + num_poses = pMultiBinPoseData->num_poses; + + IF( low_res_pre_rend_rot ) + { + num_subframes = 1; + } + ELSE + { + num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + } + + /*FILE *filePointer_gd, *filePointer_gd2; + FILE *filePointer_re, *filePointer_im; + filePointer_gd = fopen("Fixed_code_cov_gd_complete.txt", "a"); + filePointer_gd2 = fopen("Fixed_code_cov_gd2_complete.txt", "a"); + filePointer_re = fopen("Fixed_code_re_complete.txt", "a"); + filePointer_im = fopen("Fixed_code_im_complete.txt", "a");*/ + +#ifdef DUMP_GETROTMD_OUTPUT + for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + for ( b = 0; b < num_md_bands; b++ ) + { + for ( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ ) + { + if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY ) + { + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd = me2f( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_fx, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_gd ); + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2 = me2f( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_fx, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_gd2 ); + /*fprintf(filePointer_gd, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd); + fprintf(filePointer_gd2, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2);*/ + } + else + { + for ( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + for ( int j = 0; j < BINAURAL_CHANNELS; j++ ) + { + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re[i][j] = me2f( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_fx[i][j], hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_re ); + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im[i][j] = me2f( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_fx[i][j], hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_im ); + /*fprintf(filePointer_re, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re[i][j]); + fprintf(filePointer_im, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im[i][j]);*/ + } + } + } + } + } + } +#endif + + /*fclose(filePointer_gd); + fclose(filePointer_gd2); + fclose(filePointer_re); + fclose(filePointer_im);*/ + + /* Check if rescaling can be simplified/avoid */ + + Word16 exp_frame = 0; + // Word32 L_temp_max = 0; + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( b = 0; b < num_md_bands; b++ ) + { + FOR( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ ) + { + IF( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY ) + { + exp_frame = s_max( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_gd ); + exp_frame = s_max( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_gd2 ); + } + ELSE + { + exp_frame = s_max( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_re ); +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + exp_frame = s_max( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_re2 ); +#endif + exp_frame = s_max( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_im ); + } + } + } + } + // exp_frame = s_min( exp_frame, sub( 31, norm_l( L_temp_max ) ) ); + exp_frame = s_min( exp_frame, 15 ); // Considering the max value as of prediction matrices as 300 + + Word16 Q_frame = sub( Q31, exp_frame ); + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( b = 0; b < num_md_bands; b++ ) + { + FOR( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ ) + { + IF( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY ) + { + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_fx = L_shr_r( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_fx, sub( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_gd ) ); + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_fx = L_shr_r( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_fx, sub( exp_frame, hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_gd2 ) ); + /*fprintf(filePointer_gd, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd); + fprintf(filePointer_gd2, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2);*/ + } + ELSE + { + FOR( Word16 i = 0; i < BINAURAL_CHANNELS; i++ ) + { + Scale_sig32( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_fx[i], BINAURAL_CHANNELS, sub( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_re, exp_frame ) ); + Scale_sig32( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_fx[i], BINAURAL_CHANNELS, sub( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_im, exp_frame ) ); + } +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Scale_sig32( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re2, BINAURAL_CHANNELS, sub( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].exp_pred_mat_re2, exp_frame ) ); +#endif + } + } + } + } + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + isar_SplitRenderer_quant_code( hBinHrSplitPreRend, headPosition, pMultiBinPoseData, pBits, low_res_pre_rend_rot, ro_md_flag, target_md_bits, Q_frame ); +#else + isar_SplitRenderer_quant_code( hBinHrSplitPreRend, headPosition, pMultiBinPoseData, pBits, low_res_pre_rend_rot, target_md_bits, Q_frame ); +#endif +#ifdef DEBUG_QUANT_CODE_OUT + for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + for ( b = 0; b < num_md_bands; b++ ) + { + for ( pos_idx = 0; pos_idx < num_poses - 1; pos_idx++ ) + { + if ( hBinHrSplitPreRend->pose_type[pos_idx] == PITCH_ONLY ) + { + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd = fixedToFloat( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd_fx, Q_frame ); + hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2 = fixedToFloat( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2_fx, Q_frame ); + /*fprintf(filePointer_gd, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd); + fprintf(filePointer_gd2, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].gd2);*/ + } + else + { + for ( int i = 0; i < BINAURAL_CHANNELS; i++ ) + { + fixedToFloat_arrL( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_fx[i], hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re[i], Q_frame, BINAURAL_CHANNELS ); + fixedToFloat_arrL( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_fx[i], hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im[i], Q_frame, BINAURAL_CHANNELS ); + // for ( int j = 0; j < BINAURAL_CHANNELS; j++ ) + //{ + // hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re[i][j] = me2f( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re_fx[i][j], Q6 ); + // hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im[i][j] = me2f( hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im_fx[i][j], Q6 ); + // /*fprintf(filePointer_re, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_re[i][j]); + // fprintf(filePointer_im, "%f\n", hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b].pred_mat_im[i][j]);*/ + // } + } + } + } + } + } +#endif +#ifdef SPLIT_POSE_CORRECTION_DEBUG + float tmpCrendBuffer[2][L_FRAME48k], quant_val, step, minv, maxv; + IVAS_QUATERNION QuaternionsPost[MAX_PARAM_SPATIAL_SUBFRAMES], head_pos_euler; + float Cldfb_RealBuffer_Binaural_5ms[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural_5ms[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + int16_t sf_idx, pos_idx, b, ch1, ch2; + int32_t read_off, write_off; + for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + QuaternionsPost[sf_idx].w = -3.0f; + QuaternionsPost[sf_idx].x = 0.0f; + QuaternionsPost[sf_idx].y = 0.0f; + QuaternionsPost[sf_idx].z = 0.0f; + } + + hBinHrSplitPreRend->hBinHrSplitPostRend->low_Res = 1; + set_fix_rotation_mat( hBinHrSplitPreRend->hBinHrSplitPostRend->fix_pos_rot_mat, pMultiBinPoseData ); + set_pose_types( hBinHrSplitPreRend->hBinHrSplitPostRend->pose_type, pMultiBinPoseData ); + for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + Quat2EulerDegree( headPosition, &head_pos_euler.z, &head_pos_euler.y, &head_pos_euler.x ); + hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].w = -3.0f; + hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].x = roundf( head_pos_euler.x ); + hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].y = roundf( head_pos_euler.y ); + hBinHrSplitPreRend->hBinHrSplitPostRend->QuaternionsPre[sf_idx].z = roundf( head_pos_euler.z ); + } + for ( sf_idx = 0; sf_idx < 1; sf_idx++ ) + { + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + for ( b = 0; b < MAX_SPLIT_REND_MD_BANDS; b++ ) + { + hBinHrSplitPreRend->hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b] = hBinHrSplitPreRend->rot_md[pos_idx][sf_idx][b]; + BIN_HR_SPLIT_REND_MD_HANDLE hMd; + hMd = &hBinHrSplitPreRend->hBinHrSplitPostRend->rot_md[pos_idx][sf_idx][b]; + minv = -1.4f; + maxv = 1.4f; + step = ( maxv - minv ) / 62.0f; + if ( b >= 20 ) + { + float sign; + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + sign = ( hMd->pred_mat_re[ch1][ch2] >= 0.0f ) ? 1.0f : -1.0f; + IVAS_CALCULATE_ABS( hMd->pred_mat_re[ch1][ch2], hMd->pred_mat_im[ch1][ch2], hMd->pred_mat_re[ch1][ch2] ); + hMd->pred_mat_re[ch1][ch2] *= sign; + hMd->pred_mat_im[ch1][ch2] = 0.0f; + } + } + } + + for ( ch1 = 0; ch1 < BINAURAL_CHANNELS; ch1++ ) + { + for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) + { + quant_val = hMd->pred_mat_re[ch1][ch2] - hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx][ch1][ch2]; + quant_val = min( maxv, max( quant_val, minv ) ); + quant_val = (int16_t) roundf( quant_val / step ); + hMd->pred_mat_re[ch1][ch2] = quant_val * step; + hMd->pred_mat_re[ch1][ch2] += hBinHrSplitPreRend->fix_pos_rot_mat[pos_idx][ch1][ch2]; + + quant_val = hMd->pred_mat_im[ch1][ch2]; + quant_val = min( maxv, max( quant_val, minv ) ); + quant_val = (int16_t) roundf( quant_val / step ); + hMd->pred_mat_im[ch1][ch2] = quant_val * step; + } + } + } + } + } + + for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) + { + mvr2r( (float *) Cldfb_In_BinReal[0][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_RealBuffer_Binaural_5ms[0], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + mvr2r( (float *) Cldfb_In_BinReal[1][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_RealBuffer_Binaural_5ms[1], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + mvr2r( (float *) Cldfb_In_BinImag[0][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_ImagBuffer_Binaural_5ms[0], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + mvr2r( (float *) Cldfb_In_BinImag[1][sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES], (float *) Cldfb_ImagBuffer_Binaural_5ms[1], MAX_PARAM_SPATIAL_SUBFRAMES * CLDFB_NO_CHANNELS_MAX ); + isar_rend_CldfbSplitPostRendProcess( hBinHrSplitPreRend->hBinHrSplitPostRend, pMultiBinPoseData, QuaternionsPost[0], Cldfb_RealBuffer_Binaural_5ms, Cldfb_ImagBuffer_Binaural_5ms, tmpCrendBuffer, 1 ); + + { + float *pOut[2]; + char fname[200] = "ref_act_pos.wav"; + pOut[0] = tmpCrendBuffer[0]; + pOut[1] = tmpCrendBuffer[1]; + dbgwrite_wav( pOut, CLDFB_NO_COL_MAX * hBinHrSplitPreRend->hBinHrSplitPostRend->cldfbSyn[0]->no_channels, fname, 48000, 2 ); + } + } +#endif + + pop_wmops(); + return; +} + +/*------------------------------------------------------------------------- + * Function isar_splitBinPreRendOpen() + * + * + *------------------------------------------------------------------------*/ +ivas_error isar_splitBinPreRendOpen( + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + , + const int32_t output_Fs +#endif +) +{ + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinRend; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + ivas_error error; + int16_t ch; +#endif + Word16 pos_idx, sf_idx, bandIdx; + + IF( ( hBinRend = (ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE) malloc( sizeof( ISAR_BIN_HR_SPLIT_PRE_REND ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for bin split pre renderer Module \n" ) ); + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES + 1; i++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hBinRend->cldfbSynRotBinDec[i][ch] = NULL; + } + } + + for ( int16_t i = 0; i < MAX_HEAD_ROT_POSES + 1; i++ ) + { + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + if ( ( error = openCldfb( &( hBinRend->cldfbSynRotBinDec[i][ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } +#endif + + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + FOR( sf_idx = 0; sf_idx < MAX_SPLIT_MD_SUBFRAMES; sf_idx++ ) + { + FOR( bandIdx = 0; bandIdx < MAX_SPLIT_REND_MD_BANDS; bandIdx++ ) + { + hBinRend->rot_md[pos_idx][sf_idx][bandIdx].gd_fx = 0; + } + } + } + set_fix_rotation_mat_fx( hBinRend->fix_pos_rot_mat_fx, pMultiBinPoseData ); + set_pose_types_fx( hBinRend->pose_type, pMultiBinPoseData ); + + isar_split_rend_init_huff_cfg( &hBinRend->huff_cfg ); + +#ifdef SPLIT_POSE_CORRECTION_DEBUG + ivas_error error; + if ( ( error = isar_splitBinPostRendOpen( &hBinRend->hBinHrSplitPostRend, pMultiBinPoseData, 48000 ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + + *hBinHrSplitPreRend = hBinRend; + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * Function isar_splitBinPreRendClose() + * + * + *------------------------------------------------------------------------*/ + +void isar_splitBinPreRendClose( + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE *hBinHrSplitPreRend ) +{ + IF( ( *hBinHrSplitPreRend ) != NULL ) + { +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + { + Word16 i, n; + FOR( i = 0; i < MAX_HEAD_ROT_POSES + 1; i++ ) + { + FOR( n = 0; n < BINAURAL_CHANNELS; n++ ) + { + IF( ( *hBinHrSplitPreRend )->cldfbSynRotBinDec[i][n] != NULL ) + { + deleteCldfb( &( ( *hBinHrSplitPreRend )->cldfbSynRotBinDec[i][n] ) ); + ( *hBinHrSplitPreRend )->cldfbSynRotBinDec[i][n] = NULL; + } + } + } + } +#endif +#ifdef SPLIT_POSE_CORRECTION_DEBUG + isar_splitBinPostRendClose( &( *hBinHrSplitPreRend )->hBinHrSplitPostRend ); +#endif + + free( ( *hBinHrSplitPreRend ) ); + ( *hBinHrSplitPreRend ) = NULL; + } + + return; +} + + +/*-------------------------------------------------------------------------* + * isar_set_split_rend_ht_setup() + * + * + *-------------------------------------------------------------------------*/ +void isar_set_split_rend_ht_setup_fx( + SPLIT_REND_WRAPPER *hSplitrend, + IVAS_QUATERNION Quaternions[MAX_PARAM_SPATIAL_SUBFRAMES], + Word32 Rmat_fx[MAX_PARAM_SPATIAL_SUBFRAMES][3][3] ) +{ + Word16 sf, i, j; + IF( hSplitrend->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + FOR( sf = 1; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + { + Quaternions[sf] = Quaternions[0]; + + FOR( i = 0; i < 3; i++ ) + { + FOR( j = 0; j < 3; j++ ) + { + Rmat_fx[sf][i][j] = Rmat_fx[0][i][j]; + move32(); + } + } + } + } + + return; +} + +/*------------------------------------------------------------------------- + * Function isar_init_split_rend_handles() + * + * + *------------------------------------------------------------------------*/ + +void isar_init_split_rend_handles( + SPLIT_REND_WRAPPER *hSplitRendWrapper ) +{ + Word16 i; + + hSplitRendWrapper->hBinHrSplitPreRend = NULL; + hSplitRendWrapper->hCldfbHandles = NULL; + hSplitRendWrapper->hSplitBinLCLDEnc = NULL; + hSplitRendWrapper->hLc3plusEnc = NULL; + + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) + { + hSplitRendWrapper->lc3plusDelayBuffers[i] = NULL; + hSplitRendWrapper->lc3plusDelayBuffers_fx[i] = NULL; + } + hSplitRendWrapper->lc3plusDelaySamples = 0; + move32(); + + isar_init_multi_bin_pose_data_fx_enc( &hSplitRendWrapper->multiBinPoseData ); + + return; +} + + +/*------------------------------------------------------------------------- + * Function split_renderer_open_lc3plus() + * + * + *------------------------------------------------------------------------*/ + +ivas_error split_renderer_open_lc3plus( + SPLIT_REND_WRAPPER *hSplitRendWrapper, + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const Word32 OutSampleRate, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const IVAS_RENDER_FRAMESIZE isar_frame_size +#else + const int16_t num_subframes +#endif +) +{ + ivas_error error; + Word16 i, delayBufferLength; + LC3PLUS_CONFIG config; +#if defined ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t isar_frame_size_ms; + + if ( ( error = isar_framesize_to_ms( isar_frame_size, &isar_frame_size_ms ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* Check configuration validity */ + if ( isar_frame_size_ms < pSplitRendConfig->codec_frame_size_ms ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "SR codec frame doesn't fit in one output frame" ); + } +#endif + + config.lc3plus_frame_duration_us = pSplitRendConfig->codec_frame_size_ms * 1000; +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + config.ivas_frame_duration_us = ( pSplitRendConfig->dof == 0 ) ? config.lc3plus_frame_duration_us * num_subframes : 20000; +#endif + config.samplerate = OutSampleRate; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + config.isar_frame_duration_us = isar_frame_size_ms * 1000; +#endif +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + config.high_res_mode_enabled = ( pSplitRendConfig->lc3plus_highres != 0 ); +#endif + config.channels = BINAURAL_CHANNELS; + + if ( ( error = ISAR_LC3PLUS_ENC_Open( config, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + isar_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, pSplitRendConfig->poseCorrectionMode ), +#else + isar_get_lc3plus_bitrate( pSplitRendConfig->splitRendBitRate, pSplitRendConfig->poseCorrectionMode, (int16_t) ( config.isar_frame_duration_us / 1000 ) ), +#endif + &hSplitRendWrapper->hLc3plusEnc ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* This returns delay of entire LC3plus chain (enc + dec) */ + IF( ( error = ISAR_LC3PLUS_ENC_GetDelay( hSplitRendWrapper->hLc3plusEnc, &hSplitRendWrapper->lc3plusDelaySamples ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Alocate buffers for delay compensation */ + IF( pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS ) + { + delayBufferLength = (Word16) ( OutSampleRate / (int32_t) FRAMES_PER_SECOND + hSplitRendWrapper->lc3plusDelaySamples ); + FOR( i = 0; i < hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; ++i ) + { + IF( ( hSplitRendWrapper->lc3plusDelayBuffers[i] = malloc( delayBufferLength * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); + } + + set_zero( hSplitRendWrapper->lc3plusDelayBuffers[i], delayBufferLength ); + IF( ( hSplitRendWrapper->lc3plusDelayBuffers_fx[i] = malloc( delayBufferLength * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); + } + + set32_fx( hSplitRendWrapper->lc3plusDelayBuffers_fx[i], 0, delayBufferLength ); + } + hSplitRendWrapper->lc3plusDelayBuffers_q = 31; + } + ELSE + { + /* Delay is always expected to be exactly 2 CLDFB columns */ + assert( hSplitRendWrapper->lc3plusDelaySamples % ( OutSampleRate / FRAMES_PER_SEC / CLDFB_NO_COL_MAX ) == 0 ); + assert( hSplitRendWrapper->lc3plusDelaySamples / ( OutSampleRate / FRAMES_PER_SEC / CLDFB_NO_COL_MAX ) == 2 ); + + delayBufferLength = 2 /* Columns */ * 2 /* real and imag */ * CLDFB_NO_CHANNELS_MAX; + FOR( i = 0; i < hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; ++i ) + { + IF( ( hSplitRendWrapper->lc3plusDelayBuffers[i] = malloc( delayBufferLength * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); + } + + set_zero( hSplitRendWrapper->lc3plusDelayBuffers[i], delayBufferLength ); + IF( ( hSplitRendWrapper->lc3plusDelayBuffers_fx[i] = malloc( delayBufferLength * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); + } + + set32_fx( hSplitRendWrapper->lc3plusDelayBuffers_fx[i], 0, delayBufferLength ); + } + hSplitRendWrapper->lc3plusDelayBuffers_q = 31; + } + + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * Function splitRendLc3plusEncodeAndWrite() + * + * + *------------------------------------------------------------------------*/ +ivas_error splitRendLc3plusEncodeAndWrite( + SPLIT_REND_WRAPPER *hSplitBin, + ISAR_SPLIT_REND_BITS_HANDLE pBits, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const int32_t available_bits, +#endif +#else + const int32_t SplitRendBitRate, +#endif + Word32 *in[], + Word16 Q_sig ) +{ + ivas_error error; + int16_t i; + int32_t lc3plusBitstreamSize; + Word32 *channel_ptrs[MAX_HEAD_ROT_POSES * 2]; + Word16 Q_in[16]; + assert( hSplitBin->hLc3plusEnc != NULL ); + + /* Find next byte boundary and zero-pad to it */ + while ( pBits->bits_written % 8 != 0 ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 ); + } + + for ( i = 0; i < BINAURAL_CHANNELS * hSplitBin->multiBinPoseData.num_poses; ++i ) + { + channel_ptrs[i] = in[i]; + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( ( error = IVAS_LC3PLUS_ENC_SetBitrate( hSplitBin->hLc3plusEnc, available_bits * FRAMES_PER_SEC ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + + if ( ( error = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( hSplitBin->hLc3plusEnc, &lc3plusBitstreamSize ) ) != IVAS_ERR_OK ) + { + return error; + } + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + ISAR_SPLIT_REND_BITStream_write_int32( pBits, isar_get_lc3plus_bitrate_id( SplitRendBitRate ), 8 ); +#endif + /* Write bitstream */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + set16_fx( Q_in, Q_sig, 16 ); + move16(); + if ( ( error = ISAR_LC3PLUS_ENC_Encode( hSplitBin->hLc3plusEnc, channel_ptrs, &pBits->bits_buf[pBits->bits_written / 8], lc3plusBitstreamSize, Q_in ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ISAR_LC3PLUS_ENC_Encode( hSplitBin->hLc3plusEnc, channel_ptrs, &pBits->bits_buf[pBits->bits_written / 8] ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + + pBits->bits_written += 8 * lc3plusBitstreamSize; + pBits->codec = ISAR_SPLIT_REND_CODEC_LC3PLUS; + pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; + pBits->codec_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.lc3plus_frame_duration_us / 1000 ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + pBits->isar_frame_size_ms = (int16_t) ( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us / 1000 ); +#endif + return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * Function isar_renderMultiTDBinToSplitBinaural() + * + * + *------------------------------------------------------------------------*/ +ivas_error isar_renderMultiTDBinToSplitBinaural( + SPLIT_REND_WRAPPER *hSplitBin, + const IVAS_QUATERNION headPosition, + const Word32 SplitRendBitRate, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const int16_t isar_frame_size_ms, +#endif + const Word16 codec_frame_size_ms, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word16 max_bands, + // float *in[], + Word32 *in_fx[], // Q11 + Word16 Q_sig, + const Word16 low_res_pre_rend_rot, + const Word16 pcm_out_flag, + const Word16 ro_md_flag ) +{ + ivas_error error; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t bit_len, available_bits, target_md_bits, tmp_32; +#else + Word32 bit_len, available_bits, target_md_bits, actual_md_bits, tmp_32; +#endif + Word16 num_cldfb_bands, ch, slot_idx, pos_idx, num_poses; + Word16 tmp, tmp_e; + Word32 Cldfb_In_BinReal_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word32 Cldfb_In_BinImag_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word16 Q_in = Q_sig, q_final = 0; + move16(); + move16(); + // float Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + // float Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + UWord8 useLc3plus; + Word32 *in_delayed_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; + Word16 i; + Word32 num_slots; + + push_wmops( "isar_renderMultiTDBinToSplitBinaural" ); + + error = IVAS_ERR_OK; + num_poses = hSplitBin->multiBinPoseData.num_poses; + + useLc3plus = hSplitBin->hLc3plusEnc != NULL; + + IF( useLc3plus ) + { + /*this should always have the time resolution of pose correction MD. Note that this does not change frame size of LC3plus*/ + // Word16 frame_size = (Word16) ( hSplitBin->hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ); + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.samplerate, FRAMES_PER_SECOND_FX, &tmp_e ); + Word16 frame_size = shr( tmp, sub( 15, tmp_e ) ); // Q0 + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + /* Artificially delay input to head pose correction analysis by LC3plus coding delay, so that audio and metadata are in sync after decoding */ + mvl2l( hSplitBin->lc3plusDelayBuffers_fx[i] + frame_size, hSplitBin->lc3plusDelayBuffers_fx[i], (Word16) hSplitBin->lc3plusDelaySamples ); + // mvr2r( hSplitBin->lc3plusDelayBuffers[i] + frame_size, hSplitBin->lc3plusDelayBuffers[i], (int16_t) hSplitBin->lc3plusDelaySamples ); + in_delayed_fx[i] = hSplitBin->lc3plusDelayBuffers_fx[i]; + // in_delayed[i] = hSplitBin->lc3plusDelayBuffers[i]; + mvl2l( in_fx[i], hSplitBin->lc3plusDelayBuffers_fx[i] + hSplitBin->lc3plusDelaySamples, frame_size ); + // mvr2r(in[i], hSplitBin->lc3plusDelayBuffers[i] + hSplitBin->lc3plusDelaySamples, frame_size); + } + } + ELSE + { + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + in_delayed_fx[i] = in_fx[i]; + move32(); + } + } + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + actual_md_bits = pBits->bits_written; + move32(); +#endif + + test(); + test(); + IF( ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) || ( !useLc3plus && !pcm_out_flag ) ) + { + Word32 in_delayed_cldfb[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k] = { 0 }; + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ ) + { + Copy32( in_delayed_fx[i], in_delayed_cldfb[i], L_FRAME48k ); + Scale_sig32( in_delayed_cldfb[i], L_FRAME48k, -4 ); + } + Q_sig = sub( Q_sig, 4 ); + num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ? CLDFB_NO_COL_MAX : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ); + move32(); + num_cldfb_bands = hSplitBin->hCldfbHandles->cldfbAna[0]->no_channels; + move16(); + /* CLDFB Analysis*/ + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { +#ifdef SPLIT_POSE_CORRECTION_DEBUG + { + float *pOut[2]; + char fname[200] = "ref_out_pos"; + char tag[2]; + tag[0] = (char) ( '0' + pos_idx ); + tag[1] = '\0'; + strcat( fname, tag ); + strcat( fname, ".wav" ); + + pOut[0] = in_delayed[2 * pos_idx]; + pOut[1] = in_delayed[2 * pos_idx + 1]; + dbgwrite_wav( pOut, CLDFB_NO_COL_MAX * max_bands, fname, 48000, 2 ); + } + +#endif + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + HANDLE_CLDFB_FILTER_BANK temp_cldfbAna = hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]; + Scale_sig32( temp_cldfbAna->cldfb_state_fx, + sub( temp_cldfbAna->p_filter_length, temp_cldfbAna->no_channels ), sub( Q_sig, temp_cldfbAna->Q_cldfb_state ) ); + temp_cldfbAna->Q_cldfb_state = Q_sig; + move16(); + FOR( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) + { + Word16 Q_cldfb = Q_sig; + // floatToFixed_arrL(hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->cldfb_state, hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->cldfb_state_fx, Q_output, hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->p_filter_length - hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->no_channels); + cldfbAnalysis_ts_fx_fixed_q( &( in_delayed_cldfb[pos_idx * BINAURAL_CHANNELS + ch][num_cldfb_bands * slot_idx] ), + Cldfb_In_BinReal_fx[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], + Cldfb_In_BinImag_fx[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], + max_bands, + temp_cldfbAna, + &Q_cldfb ); + /*fixedToFloat_arrL(hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->cldfb_state, Q_output, hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->p_filter_length - hSplitBin->hCldfbHandles->cldfbAna[pos_idx * BINAURAL_CHANNELS + ch]->no_channels); + fixedToFloat_arrL(Cldfb_In_BinReal_fx[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinReal[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], Q_cldfb, max_bands); + fixedToFloat_arrL(Cldfb_In_BinImag_fx[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinImag[pos_idx * BINAURAL_CHANNELS + ch][slot_idx], Q_cldfb, max_bands);*/ + /*for (int k = 0; k < max_bands; k++) { + printf("\n%f %f ", Cldfb_In_BinReal[pos_idx * BINAURAL_CHANNELS + ch][slot_idx][k], Cldfb_In_BinImag[pos_idx * BINAURAL_CHANNELS + ch][slot_idx][k]); + }*/ + } + } + } + q_final = sub( Q_sig, 5 ); + } + + IF( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + // target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000; + target_md_bits = W_extract_l( W_mult0_32_32( isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ), L_FRAME48k ) ); + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( target_md_bits, 48000, &tmp_e ); + target_md_bits = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + actual_md_bits = pBits->bits_written; +#endif + /*scaling to max Q*/ + Word16 scale_factor = 31; + move32(); + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + scale_factor = s_min( scale_factor, s_min( getScaleFactor32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX ), getScaleFactor32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX ) ) ); + } + } + scale_factor = sub( scale_factor, 2 ); + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX, scale_factor ); + Scale_sig32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX, scale_factor ); + } + } + q_final = add( q_final, scale_factor ); + Word16 exp_cldfb_re = sub( 31, q_final ); + Word16 exp_cldfb_im = sub( 31, q_final ); + isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal_fx, exp_cldfb_re, Cldfb_In_BinImag_fx, exp_cldfb_im, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag ); + } + + IF( EQ_16( pcm_out_flag, 0 ) ) + { + pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; + pBits->codec = useLc3plus ? ISAR_SPLIT_REND_CODEC_LC3PLUS : ISAR_SPLIT_REND_CODEC_LCLD; + + IF( !useLc3plus ) + { + // available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); + available_bits = W_extract_l( W_mult0_32_32( SplitRendBitRate, L_mult0( hSplitBin->hSplitBinLCLDEnc->iNumBlocks, hSplitBin->hSplitBinLCLDEnc->iNumIterations ) ) ); + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( available_bits, L_mult0( 16, FRAMES_PER_SEC ), &tmp_e ); + available_bits = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + available_bits = L_sub( available_bits, pBits->bits_written ); +#else + actual_md_bits = L_sub( pBits->bits_written, actual_md_bits ); + available_bits = L_sub( available_bits, actual_md_bits ); +#endif + pBits->codec_frame_size_ms = codec_frame_size_ms; + move16(); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + pBits->isar_frame_size_ms = isar_frame_size_ms; + move16(); +#endif + isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal_fx, Cldfb_In_BinImag_fx, available_bits, pBits, &q_final ); + } + ELSE + { +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written; + IF( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, in_fx, Q_in ) ) != IVAS_ERR_OK ) + { + return error; + } +#else + IF( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, SplitRendBitRate, in_flt ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + } + } + ELSE + { + pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; + pBits->codec = ISAR_SPLIT_REND_CODEC_NONE; + } + + /*zero pad*/ + IF( pcm_out_flag ) + { + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( SplitRendBitRate, FRAMES_PER_SEC, &tmp_e ); + bit_len = L_deposit_l( shr( tmp, sub( 15, tmp_e ) ) ); // Q0 + // bit_len = SplitRendBitRate / FRAMES_PER_SEC; + } + ELSE + { + IF( !useLc3plus ) + { + // bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); + + bit_len = W_extract_l( W_mult0_32_32( SplitRendBitRate, L_mult0( hSplitBin->hSplitBinLCLDEnc->iNumBlocks, hSplitBin->hSplitBinLCLDEnc->iNumIterations ) ) ); + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( bit_len, L_mult0( 16, FRAMES_PER_SEC ), &tmp_e ); + bit_len = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 + } + ELSE + { + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( (Word32) hSplitBin->hLc3plusEnc->config.isar_frame_duration_us, 1000, &tmp_e ); + bit_len = L_deposit_l( shr( tmp, sub( 15, tmp_e ) ) ); // Q0 + // bit_len = hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000; + // bit_len = SplitRendBitRate * bit_len / 1000; + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( W_extract_l( W_mult0_32_32( SplitRendBitRate, bit_len ) ), 1000, &tmp_e ); + bit_len = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 + } + } + + + WHILE( LT_32( pBits->bits_written, bit_len ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 ); + } + + pop_wmops(); + + return error; +} + +/*------------------------------------------------------------------------- + * Function lc3plusTimeAlignCldfbPoseCorr() + * + * + *------------------------------------------------------------------------*/ +void lc3plusTimeAlignCldfbPoseCorr( + SPLIT_REND_WRAPPER *hSplitBin, + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 *Q_in ) +{ + Word32 Cldfb_In_BinReal_tmp_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_In_BinImag_tmp_fx[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][2][CLDFB_NO_CHANNELS_MAX]; + Word16 pose, ch, slot_idx; + Word32 *bufRead_fx, *bufWrite_fx; + + IF( GT_16( hSplitBin->lc3plusDelayBuffers_q, *Q_in ) ) + { + // hSplitBin->lc3plusDelayBuffers_q[0] = *Q_in; + FOR( Word16 i = 0; i < hSplitBin->multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ ) + { + + Scale_sig32( hSplitBin->lc3plusDelayBuffers_fx[i], 4 * CLDFB_NO_CHANNELS_MAX, sub( *Q_in, hSplitBin->lc3plusDelayBuffers_q ) ); + } + hSplitBin->lc3plusDelayBuffers_q = *Q_in; + } + ELSE + { + FOR( Word16 i = 0; i < CLDFB_NO_COL_MAX; i++ ) + { + for ( Word16 j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( hSplitBin->lc3plusDelayBuffers_q, *Q_in ) ); + Scale_sig32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( hSplitBin->lc3plusDelayBuffers_q, *Q_in ) ); + } + } + *Q_in = hSplitBin->lc3plusDelayBuffers_q; + } + + FOR( pose = 0; pose < hSplitBin->multiBinPoseData.num_poses; ++pose ) + { + FOR( ch = 0; ch < BINAURAL_CHANNELS; ++ch ) + { + bufRead_fx = hSplitBin->lc3plusDelayBuffers_fx[pose * BINAURAL_CHANNELS + ch]; + bufWrite_fx = bufRead_fx; + + /* Save last 2 columns for next frame */ + FOR( slot_idx = 0; slot_idx < 2; ++slot_idx ) + { + Copy32( Cldfb_In_BinReal_fx[pose * BINAURAL_CHANNELS + ch][CLDFB_NO_COL_MAX - 2 + slot_idx], Cldfb_In_BinReal_tmp_fx[pose][ch][slot_idx], CLDFB_NO_CHANNELS_MAX ); + Copy32( Cldfb_In_BinImag_fx[pose * BINAURAL_CHANNELS + ch][CLDFB_NO_COL_MAX - 2 + slot_idx], Cldfb_In_BinImag_tmp_fx[pose][ch][slot_idx], CLDFB_NO_CHANNELS_MAX ); + } + + /* Delay existing columns by 2 slots */ + /*TODO : shouldnt the delay be 7.5 ms ? 5ms + LC3plus delay */ + FOR( slot_idx = CLDFB_NO_COL_MAX - 2 - 1; slot_idx >= 0; --slot_idx ) + { + Copy32( Cldfb_In_BinReal_fx[pose * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinReal_fx[pose * BINAURAL_CHANNELS + ch][slot_idx + 2], CLDFB_NO_CHANNELS_MAX ); + Copy32( Cldfb_In_BinImag_fx[pose * BINAURAL_CHANNELS + ch][slot_idx], Cldfb_In_BinImag_fx[pose * BINAURAL_CHANNELS + ch][slot_idx + 2], CLDFB_NO_CHANNELS_MAX ); + } + + /* Fill 2 first columns from buffer */ + FOR( slot_idx = 0; slot_idx < 2; ++slot_idx ) + { + Copy32( bufRead_fx, Cldfb_In_BinReal_fx[pose * BINAURAL_CHANNELS + ch][slot_idx], CLDFB_NO_CHANNELS_MAX ); + bufRead_fx += CLDFB_NO_CHANNELS_MAX; + Copy32( bufRead_fx, Cldfb_In_BinImag_fx[pose * BINAURAL_CHANNELS + ch][slot_idx], CLDFB_NO_CHANNELS_MAX ); + bufRead_fx += CLDFB_NO_CHANNELS_MAX; + } + + /* Copy last 2 columns to buffer */ + FOR( slot_idx = 0; slot_idx < 2; ++slot_idx ) + { + Copy32( Cldfb_In_BinReal_tmp_fx[pose][ch][slot_idx], bufWrite_fx, CLDFB_NO_CHANNELS_MAX ); + bufWrite_fx += CLDFB_NO_CHANNELS_MAX; + Copy32( Cldfb_In_BinImag_tmp_fx[pose][ch][slot_idx], bufWrite_fx, CLDFB_NO_CHANNELS_MAX ); + bufWrite_fx += CLDFB_NO_CHANNELS_MAX; + } + } + } + + return; +} + +#endif diff --git a/lib_isar/isar_splitRenderer_utils.c b/lib_isar/isar_splitRenderer_utils.c new file mode 100644 index 000000000..b290ca12a --- /dev/null +++ b/lib_isar/isar_splitRenderer_utils.c @@ -0,0 +1,1741 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "ivas_prot.h" +#include "prot.h" +#include "cnst.h" +#include "isar_cnst.h" +#include "ivas_rom_rend.h" +#include "ivas_rom_com.h" +#include "isar_rom_post_rend.h" +#include "ivas_rom_binauralRenderer.h" +#include "lib_isar_post_rend.h" +#include "isar_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" +#include "basop_settings.h" +#include "prot_fx2.h" + +#include "basop_util.h" + + +/*------------------------------------------------------------------------- + * Function ivas_mat_mult_2by2_complex() + * + * + *------------------------------------------------------------------------*/ +void ivas_cmult_fix( Word32 in1_re_fx, Word16 exp_re1, Word32 in1_im_fx, Word16 exp_im1, Word32 in2_re_fx, Word16 exp_re2, Word32 in2_im_fx, Word16 exp_im2, Word32 *out1_re_fx, Word32 *out1_im_fx, Word16 *exp_out1_re, Word16 *exp_out1_im ) +{ + Word16 shift_1 = W_norm( W_mult_32_32( in1_re_fx, in2_re_fx ) ); + Word16 shift_2 = W_norm( W_mult_32_32( in1_im_fx, in2_im_fx ) ); + Word32 tmp1 = W_extract_h( W_shl( W_mult_32_32( in1_re_fx, in2_re_fx ), shift_1 ) ); + Word32 tmp2 = W_extract_h( W_shl( W_mult_32_32( in1_im_fx, in2_im_fx ), shift_2 ) ); + Word16 exp_tmp1 = 0; + move16(); + *out1_re_fx = BASOP_Util_Add_Mant32Exp( tmp1, exp_re1 + exp_re2 - shift_1, L_negate( tmp2 ), exp_im1 + exp_im2 - shift_2, &exp_tmp1 ); + *exp_out1_re = exp_tmp1; + Word16 shift_3 = W_norm( W_mult_32_32( in1_re_fx, in2_im_fx ) ); + Word16 shift_4 = W_norm( W_mult_32_32( in2_re_fx, in1_im_fx ) ); + Word32 tmp3 = W_extract_h( W_shl( W_mult_32_32( in1_re_fx, in2_im_fx ), shift_3 ) ); + Word32 tmp4 = W_extract_h( W_shl( W_mult_32_32( in2_re_fx, in1_im_fx ), shift_4 ) ); + Word16 exp_tmp2 = 0; + move16(); + *out1_im_fx = BASOP_Util_Add_Mant32Exp( tmp3, exp_re1 + exp_im2 - shift_3, tmp4, exp_re2 + exp_im1 - shift_4, &exp_tmp2 ); + *exp_out1_im = exp_tmp2; + move16(); +} + +void ivas_calculate_abs_fx( Word32 re_fx, Word16 exp_re, Word32 im_fx, Word16 exp_im, Word32 *out_fx, Word16 *exp_out ) +{ + Word16 shift_1 = W_norm( W_mult_32_32( re_fx, re_fx ) ); + Word16 shift_2 = W_norm( W_mult_32_32( im_fx, im_fx ) ); + Word32 tmp1 = W_extract_h( W_shl( W_mult_32_32( re_fx, re_fx ), shift_1 ) ); + Word32 tmp2 = W_extract_h( W_shl( W_mult_32_32( im_fx, im_fx ), shift_2 ) ); + Word16 exp_tmp1 = 0; + Word32 tmp3 = BASOP_Util_Add_Mant32Exp( tmp1, exp_re + exp_re - shift_1, tmp2, exp_im + exp_im - shift_2, &exp_tmp1 ); + *out_fx = Sqrt32( tmp3, &exp_tmp1 ); + *exp_out = exp_tmp1; +} + +void ivas_calculate_rabs_fx( Word32 re_fx, Word16 exp_re, Word32 *out_fx, Word16 *exp_out ) +{ + Word16 shift_1 = W_norm( W_mult_32_32( re_fx, re_fx ) ); + Word32 tmp1 = W_extract_h( W_shl( W_mult_32_32( re_fx, re_fx ), shift_1 ) ); + Word16 exp_tmp1 = exp_re + exp_re - shift_1; + Word32 tmp2 = Sqrt32( tmp1, &exp_tmp1 ); + *out_fx = tmp2; + *exp_out = exp_tmp1; +} + +void isar_mat_mult_2by2_complex_fx( + Word32 in_re1_fx[2][2], + Word16 exp_re1, + Word32 in_im1_fx[2][2], + Word16 exp_im1, + Word32 in_re2_fx[2][2], + Word16 exp_re2, + Word32 in_im2_fx[2][2], + Word16 exp_im2, + Word32 out_re2_fx[2][2], + Word16 *final_exp_re_1, + Word32 out_im2_fx[2][2], + Word16 *final_exp_im_1 ) +{ + Word16 i, j; + Word32 tmp_re_fx, tmp_im_fx; + + Word16 exp_tmp1 = 0, exp_tmp2 = 0, exp_tmp3 = 0, exp_tmp4 = 0; + Word16 final_exp_re = 0, final_exp_im = 0; + Word16 BuffExp_re[2][2]; + Word16 BuffExp_im[2][2]; + + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 2; j++ ) + { + ivas_cmult_fix( in_re1_fx[i][0], exp_re1, in_im1_fx[i][0], exp_im1, in_re2_fx[0][j], exp_re2, in_im2_fx[0][j], exp_im2, &tmp_re_fx, &tmp_im_fx, &exp_tmp1, &exp_tmp2 ); + + out_re2_fx[i][j] = tmp_re_fx; + move32(); + out_im2_fx[i][j] = tmp_im_fx; + move32(); + + ivas_cmult_fix( in_re1_fx[i][1], exp_re1, in_im1_fx[i][1], exp_im1, in_re2_fx[1][j], exp_re2, in_im2_fx[1][j], exp_im2, &tmp_re_fx, &tmp_im_fx, &exp_tmp3, &exp_tmp4 ); + + out_re2_fx[i][j] = BASOP_Util_Add_Mant32Exp( out_re2_fx[i][j], exp_tmp1, tmp_re_fx, exp_tmp3, &final_exp_re ); + move32(); + out_im2_fx[i][j] = BASOP_Util_Add_Mant32Exp( out_im2_fx[i][j], exp_tmp2, tmp_im_fx, exp_tmp4, &final_exp_im ); + move32(); + + BuffExp_re[i][j] = final_exp_re; + move16(); + BuffExp_im[i][j] = final_exp_im; + move16(); + } + } + + Word16 max_exp_re = 0; + Word16 max_exp_im = 0; + move16(); + move16(); + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 2; j++ ) + { + max_exp_re = s_max( max_exp_re, BuffExp_re[i][j] ); + max_exp_im = s_max( max_exp_im, BuffExp_im[i][j] ); + } + } + + FOR( i = 0; i < 2; i++ ) + { + FOR( j = 0; j < 2; j++ ) + { + out_re2_fx[i][j] = L_shr( out_re2_fx[i][j], max_exp_re - BuffExp_re[i][j] ); + move32(); + out_im2_fx[i][j] = L_shr( out_im2_fx[i][j], max_exp_im - BuffExp_im[i][j] ); + move32(); + } + } + *final_exp_re_1 = max_exp_re; + move16(); + *final_exp_im_1 = max_exp_im; + move16(); + + return; +} + +void ivas_mat_mult_2by2_complex( + float in_re1[2][2], + float in_im1[2][2], + float in_re2[2][2], + float in_im2[2][2], + float out_re2[2][2], + float out_im2[2][2] ) +{ + int16_t i, j; + float tmp_re, tmp_im; + + for ( i = 0; i < 2; i++ ) + { + for ( j = 0; j < 2; j++ ) + { + IVAS_CMULT_FLOAT( in_re1[i][0], in_im1[i][0], in_re2[0][j], in_im2[0][j], tmp_re, tmp_im ); + out_re2[i][j] = tmp_re; + out_im2[i][j] = tmp_im; + + IVAS_CMULT_FLOAT( in_re1[i][1], in_im1[i][1], in_re2[1][j], in_im2[1][j], tmp_re, tmp_im ); + out_re2[i][j] += tmp_re; + out_im2[i][j] += tmp_im; + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function ISAR_SPLIT_REND_BITStream_init() + * + * + *------------------------------------------------------------------------*/ + +void ISAR_SPLIT_REND_BITStream_init( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 buf_len_bytes, + UWord8 *pbuf ) +{ + pBits->bits_buf = pbuf; + pBits->buf_len = buf_len_bytes; + move32(); + pBits->bits_read = 0; + move32(); + pBits->bits_written = 0; + move32(); + + return; +} + + +/*------------------------------------------------------------------------- + * Function isar_split_rend_huffman_dec_init_min_max_len() + * + * + *------------------------------------------------------------------------*/ + +void isar_split_rend_huffman_dec_init_min_max_len( + isar_split_rend_huffman_cfg_t *p_huff_cfg ) +{ + Word16 i, code_len; + const Word32 *codebook; + + codebook = p_huff_cfg->codebook; + + p_huff_cfg->min_len = p_huff_cfg->sym_len; + move16(); + p_huff_cfg->max_len = 0; + move16(); + + FOR( i = 0; i < p_huff_cfg->sym_len; i++ ) + { + code_len = extract_l( codebook[1] ); + IF( GT_16( p_huff_cfg->min_len, code_len ) ) + { + p_huff_cfg->min_len = code_len; + move16(); + } + IF( LT_16( p_huff_cfg->max_len, code_len ) ) + { + p_huff_cfg->max_len = code_len; + move16(); + } + codebook = codebook + 3; + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function is_idx_present() + * + * + *------------------------------------------------------------------------*/ + +static Word16 is_idx_present( + Word16 *idx_list, + const Word16 idx, + const Word16 len ) +{ + Word16 i; + + FOR( i = 0; i < len; i++ ) + { + IF( EQ_16( idx_list[i], idx ) ) + { + return 1; + } + } + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function ivas_split_huff_get_idx_trav_list() + * + * + *------------------------------------------------------------------------*/ + +static void ivas_split_huff_get_idx_trav_list( + Word16 *idx_list, + isar_split_rend_huffman_cfg_t *p_huff_cfg ) +{ + Word16 i, j, min_idx; + Word32 min_bits; + const Word32 *codebook; + + FOR( i = 0; i < p_huff_cfg->sym_len; i++ ) + { + idx_list[i] = -1; + move16(); + } + + FOR( i = 0; i < p_huff_cfg->sym_len; i++ ) + { + codebook = p_huff_cfg->codebook; + min_bits = p_huff_cfg->max_len; + move16(); + min_idx = -1; + move16(); + FOR( j = 0; j < p_huff_cfg->sym_len; j++ ) + { + test(); + IF( GE_32( min_bits, codebook[1] ) && EQ_16( is_idx_present( idx_list, j, i + 1 ), 0 ) ) + { + min_bits = codebook[1]; + move16(); + min_idx = j; + move16(); + } + codebook += 3; + } + idx_list[i] = min_idx; + move16(); + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function isar_split_rend_init_huff_cfg() + * + * + *------------------------------------------------------------------------*/ + +void isar_split_rend_init_huff_cfg( + ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg ) +{ + pHuff_cfg->pred[0].codebook = &ivas_split_rend_huff_pred31_consts[0][0]; + pHuff_cfg->pred[0].sym_len = ISAR_SPLIT_REND_PRED_31QUANT_PNTS; + move16(); + isar_split_rend_huffman_dec_init_min_max_len( &pHuff_cfg->pred[0] ); + ivas_split_huff_get_idx_trav_list( pHuff_cfg->pred_idx_trav[0], &pHuff_cfg->pred[0] ); + pHuff_cfg->pred_base2_code_len[0] = ISAR_SPLIT_REND_PRED_31QUANT_PNTS_LOG2_CEIL; + move16(); + + pHuff_cfg->pred[1].codebook = &ivas_split_rend_huff_pred63_consts[0][0]; + pHuff_cfg->pred[1].sym_len = ISAR_SPLIT_REND_PRED_63QUANT_PNTS; + move16(); + isar_split_rend_huffman_dec_init_min_max_len( &pHuff_cfg->pred[1] ); + ivas_split_huff_get_idx_trav_list( pHuff_cfg->pred_idx_trav[1], &pHuff_cfg->pred[1] ); + pHuff_cfg->pred_base2_code_len[1] = ISAR_SPLIT_REND_PRED_63QUANT_PNTS_LOG2_CEIL; + move16(); + + + pHuff_cfg->pred_roll.codebook = &ivas_split_rend_huff_roll_pred_consts[0][0]; + pHuff_cfg->pred_roll.sym_len = ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS; + move16(); + isar_split_rend_huffman_dec_init_min_max_len( &pHuff_cfg->pred_roll ); + ivas_split_huff_get_idx_trav_list( pHuff_cfg->pred_roll_idx_trav, &pHuff_cfg->pred_roll ); + pHuff_cfg->pred_roll_base2_code_len = ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS_LOG2_CEIL; + move16(); + + pHuff_cfg->gd.codebook = &ivas_split_rend_huff_d_consts[0][0]; + pHuff_cfg->gd.sym_len = ISAR_SPLIT_REND_D_QUANT_PNTS; + move16(); + isar_split_rend_huffman_dec_init_min_max_len( &pHuff_cfg->gd ); + ivas_split_huff_get_idx_trav_list( pHuff_cfg->gd_idx_trav, &pHuff_cfg->gd ); + pHuff_cfg->gd_base2_code_len = ISAR_SPLIT_REND_D_QUANT_PNTS_LOG2_CEIL; + move16(); + + pHuff_cfg->p_gd.codebook = &ivas_split_rend_huff_p_d_consts[0][0]; + pHuff_cfg->p_gd.sym_len = ISAR_SPLIT_REND_D_QUANT_PNTS; + move16(); + isar_split_rend_huffman_dec_init_min_max_len( &pHuff_cfg->p_gd ); + ivas_split_huff_get_idx_trav_list( pHuff_cfg->p_gd_idx_trav, &pHuff_cfg->p_gd ); + pHuff_cfg->p_gd_base2_code_len = ISAR_SPLIT_REND_D_QUANT_PNTS_LOG2_CEIL; + move16(); + + pHuff_cfg->p_gd_diff.codebook = &ivas_split_rend_huff_p_d_diff_consts[0][0]; + pHuff_cfg->p_gd_diff.sym_len = ISAR_SPLIT_REND_D_QUANT_PNTS; + move16(); + isar_split_rend_huffman_dec_init_min_max_len( &pHuff_cfg->p_gd_diff ); + ivas_split_huff_get_idx_trav_list( pHuff_cfg->p_gd_diff_idx_trav, &pHuff_cfg->p_gd_diff ); + pHuff_cfg->p_gd_diff_base2_code_len = ISAR_SPLIT_REND_D_QUANT_PNTS_LOG2_CEIL; + move16(); + + return; +} + + +/*------------------------------------------------------------------------- + * Function set_fix_rotation_mat() + * + * + *------------------------------------------------------------------------*/ + +void set_fix_rotation_mat_fx( + Word32 fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + Word32 cos_yaw, sin_yaw; + Word16 pos_idx; + Word16 ind = 0; + + // pMultiBinPoseData->relative_head_poses can take only take -30, -22.5, -15, 0, 15, 22.5 and 30 degrees. + // cos(180 - theta) = cos(theta). + // Need only 4 values in LUT + + FOR( pos_idx = 0; pos_idx < sub( pMultiBinPoseData->num_poses, 1 ); pos_idx++ ) + { + ind = extract_l( L_shr( L_abs( pMultiBinPoseData->relative_head_poses_fx[pos_idx + 1][0] ), Q22 ) ); + + ind = shr( ind, 3 ); /* Values: 0, 1, 2 and 3 */ + cos_yaw = ivas_split_rend_fix_pos_rot_mat_cos_fx[ind]; /* Q31 */ + sin_yaw = 0; + + fix_pos_rot_mat[pos_idx][0][0] = cos_yaw; /* Q31 */ + fix_pos_rot_mat[pos_idx][1][1] = cos_yaw; /* Q31 */ + fix_pos_rot_mat[pos_idx][0][1] = sin_yaw; /* Q31 */ + fix_pos_rot_mat[pos_idx][1][0] = L_negate( sin_yaw ); /* Q31 */ + } + + return; +} +void set_fix_rotation_mat( + float fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + float yaw_a, cos_yaw, sin_yaw; + int16_t pos_idx; + yaw_a = 0.0f; + + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + yaw_a = pMultiBinPoseData->relative_head_poses[pos_idx + 1][0]; + cos_yaw = cosf( EVS_PI * yaw_a / 180.0f ); + sin_yaw = sinf( EVS_PI * yaw_a / 180.0f ); + sin_yaw = 0.0f; + fix_pos_rot_mat[pos_idx][0][0] = cos_yaw; + fix_pos_rot_mat[pos_idx][1][1] = cos_yaw; + fix_pos_rot_mat[pos_idx][0][1] = sin_yaw; + fix_pos_rot_mat[pos_idx][1][0] = -1.0f * sin_yaw; + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function set_pose_types() + * + * + *------------------------------------------------------------------------*/ + +void set_pose_types_fx( + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + Word16 pos_idx; + + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + IF( GT_32( L_abs( pMultiBinPoseData->relative_head_poses_fx[pos_idx + 1][0] ), EPSILON_FX ) ) + { + pose_type[pos_idx] = ANY_YAW; + move32(); + } + ELSE IF( GT_32( L_abs( pMultiBinPoseData->relative_head_poses_fx[pos_idx + 1][2] ), EPSILON_FX ) ) + { + pose_type[pos_idx] = ANY_ROLL; + move32(); + } + ELSE + { + pose_type[pos_idx] = PITCH_ONLY; + move32(); + } + } + + return; +} +void set_pose_types( + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + int16_t pos_idx; + + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) + { + if ( fabs( pMultiBinPoseData->relative_head_poses[pos_idx + 1][0] ) > EPSILON ) + { + pose_type[pos_idx] = ANY_YAW; + } + else if ( fabs( pMultiBinPoseData->relative_head_poses[pos_idx + 1][2] ) > EPSILON ) + { + pose_type[pos_idx] = ANY_ROLL; + } + else + { + pose_type[pos_idx] = PITCH_ONLY; + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * Function wrap_a() + * + * + *------------------------------------------------------------------------*/ + +Word16 wrap_a( + Word16 val, + const Word16 min_val, + const Word16 max_val ) +{ + IF( LT_16( val, min_val ) ) + { + val = add( add( sub( max_val, min_val ), val ), 1 ); + } + + IF( GT_16( val, max_val ) ) + { + val = sub( sub( add( min_val, val ), max_val ), 1 ); + } + + return val; +} + + +/*------------------------------------------------------------------------- + * Function isar_SplitRenderer_getdiagdiff() + * + * + *------------------------------------------------------------------------*/ + +void isar_SplitRenderer_getdiagdiff( + Word16 in_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + Word16 out_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], + const Word16 sign, + const Word16 min_val, + const Word16 max_val ) +{ + out_idx[0][0] = in_idx[0][0]; + move16(); + out_idx[0][1] = in_idx[0][1]; + move16(); + // DEPR_i_mult used instead of i_mult becuase it is not available + out_idx[1][1] = add( in_idx[1][1], DEPR_i_mult( sign, out_idx[0][0] ) ); + move16(); + out_idx[1][1] = wrap_a( out_idx[1][1], min_val, max_val ); + move16(); + out_idx[1][0] = add( in_idx[1][0], DEPR_i_mult( sign, out_idx[0][1] ) ); + move16(); + out_idx[1][0] = wrap_a( out_idx[1][0], min_val, max_val ); + move16(); + + return; +} + + +/*------------------------------------------------------------------------- + * Function ISAR_SPLIT_REND_BITStream_read_int32() + * + * + *------------------------------------------------------------------------*/ +Word32 ISAR_SPLIT_REND_BITStream_read_int32( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 bits ) +{ + Word32 val, k, bit_val; + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + assert( ( pBits->bits_written - pBits->bits_read ) >= bits ); + assert( bits <= 32 ); +#endif + + /* write bit by bit */ + val = 0; + move32(); + FOR( k = L_sub( bits, 1 ); k >= 0; k-- ) + { + bit_val = NE_32( L_and( pBits->bits_buf[L_shr( pBits->bits_read, 3 )], ( L_shl( 1, (Word16) ( L_and( pBits->bits_read, 7 ) ) ) ) ), 0 ); + val = L_or( val, L_shl( bit_val, (Word16) k ) ); + pBits->bits_read = L_add( pBits->bits_read, 1 ); + } + + return val; +} + + +/*------------------------------------------------------------------------- + * Function ISAR_SPLIT_REND_BITStream_write_int32() + * + * + *------------------------------------------------------------------------*/ + +void ISAR_SPLIT_REND_BITStream_write_int32( + ISAR_SPLIT_REND_BITS_HANDLE pBits, + const Word32 val, + const Word32 bits ) +{ + Word32 mask, k; + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + /*protection check*/ + if ( ( pBits->buf_len << 3 ) < ( pBits->bits_written + bits ) ) + { + assert( 0 ); + } +#endif + + mask = L_shl( 1, extract_l( L_sub( bits, 1 ) ) ); + /* write bit by bit */ + FOR( k = 0; k < bits; k++ ) + { + IF( L_and( val, mask ) ) + { + pBits->bits_buf[L_shr( pBits->bits_written, 3 )] = (UWord8) L_or( pBits->bits_buf[L_shr( pBits->bits_written, 3 )], L_shl( 1, extract_l( L_and( pBits->bits_written, 7 ) ) ) ); + } + ELSE + { + pBits->bits_buf[L_shr( pBits->bits_written, 3 )] = (UWord8) L_and( pBits->bits_buf[L_shr( pBits->bits_written, 3 )], ~L_shl( 1, extract_l( L_and( pBits->bits_written, 7 ) ) ) ); + } + pBits->bits_written++; + mask = L_shr( mask, 1 ); + } + + return; +} + + +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG +/*------------------------------------------------------------------------- + * ivas_mat_mult_2by2_complex() + * + * + *------------------------------------------------------------------------*/ + +void isar_log_cldfb2wav_data( + float Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + HANDLE_CLDFB_FILTER_BANK *cldfbSyn, + const int16_t num_chs, + const int16_t num_freq_bands, + const int32_t output_Fs, + const int16_t num_slots, + const int16_t start_slot_idx, + const char *filename ) +{ + float *RealBuffer[CLDFB_NO_COL_MAX]; + float *ImagBuffer[CLDFB_NO_COL_MAX]; + float pcm_out[BINAURAL_CHANNELS][L_FRAME48k]; + float *pPcm[BINAURAL_CHANNELS]; + float Cldfb_local_Real[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_local_Imag[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + int16_t sf, ch; + + assert( num_chs <= BINAURAL_CHANNELS ); + for ( ch = 0; ch < num_chs; ch++ ) + { + for ( sf = start_slot_idx; sf < start_slot_idx + num_slots; sf++ ) + { + mvr2r( Cldfb_In_Real[ch][sf], Cldfb_local_Real[ch][sf], num_freq_bands ); + mvr2r( Cldfb_In_Imag[ch][sf], Cldfb_local_Imag[ch][sf], num_freq_bands ); + RealBuffer[sf - start_slot_idx] = Cldfb_local_Real[ch][sf]; + ImagBuffer[sf - start_slot_idx] = Cldfb_local_Imag[ch][sf]; + } + cldfbSynthesis( RealBuffer, ImagBuffer, &( pcm_out[ch][0] ), num_freq_bands * num_slots, cldfbSyn[ch] ); + pPcm[ch] = pcm_out[ch]; + } + dbgwrite_wav( pPcm, num_freq_bands * num_slots, filename, output_Fs, num_chs ); + + return; +} +#endif + + +/*------------------------------------------------------------------------- + * Function isar_get_split_rend_md_target_brate() + * + * + *------------------------------------------------------------------------*/ + +Word32 isar_get_split_rend_md_target_brate( + const Word32 SplitRendBitRate, + const Word16 pcm_out_flag ) +{ + Word32 md_bitrate; + + IF( EQ_16( pcm_out_flag, 1 ) ) + { + md_bitrate = SplitRendBitRate; + move32(); + } + ELSE + { + SWITCH( SplitRendBitRate ) + { + case SPLIT_REND_768k: + { + md_bitrate = 256000; + move32(); + BREAK; + } + case SPLIT_REND_512k: + { + md_bitrate = 128000; + move32(); + BREAK; + } + case SPLIT_REND_384k: + { + md_bitrate = 128000; + move32(); + BREAK; + } + default: + { + return -1; + } + } + } + + return md_bitrate; +} + + +/*------------------------------------------------------------------------- + * Function isar_get_lcld_bitrate() + * + * + *------------------------------------------------------------------------*/ + +Word32 isar_get_lcld_bitrate( + const Word32 SplitRendBitRate, + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode ) +{ + IF( EQ_32( poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + { + SWITCH( SplitRendBitRate ) + { + case SPLIT_REND_768k: + { + return IVAS_512k; + } + case SPLIT_REND_512k: + { + return IVAS_384k; + } + case SPLIT_REND_384k: + { + return IVAS_256k; + } + default: + { + assert( 0 ); + } + } + } + ELSE + { + return SplitRendBitRate; + } + + return -1; +} + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS +/*------------------------------------------------------------------------- + * Function isar_get_lc3plus_bitrate() + * + * + *------------------------------------------------------------------------*/ + +Word32 isar_get_lc3plus_bitrate( + const Word32 SplitRendBitRate, + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, + const Word16 split_prerender_frame_size_ms ) +{ + IF( EQ_32( poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + { + Word32 inBandMdBps = (Word32) ( 8 * 1000 / split_prerender_frame_size_ms ); + return L_sub( isar_get_lcld_bitrate( SplitRendBitRate, poseCorrectionMode ), inBandMdBps ); + } + + IF( EQ_32( poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ) + { + return SplitRendBitRate; + } + + /* Should not be reached */ + assert( 0 ); + return -1; +} + + +/*------------------------------------------------------------------------- + * Function isar_get_lc3plus_bitrate_id() + * + * + *------------------------------------------------------------------------*/ + +Word8 isar_get_lc3plus_bitrate_id( + const Word32 SplitRendBitRate ) +{ + SWITCH( SplitRendBitRate ) + { + case SPLIT_REND_768k: + { + return 4; + } + case SPLIT_REND_512k: + { + return 3; + } + case SPLIT_REND_384k: + { + return 2; + } + case SPLIT_REND_320k: + { + return 1; + } + case SPLIT_REND_256k: + { + return 0; + } + default: + { + BREAK; + } + } + + return -1; +} + + +/*------------------------------------------------------------------------- + * Function ivas_mat_mult_2by2_complex() + * + * + *------------------------------------------------------------------------*/ + +Word32 isar_get_lc3plus_size_from_id( + const Word8 SplitRendBitRateId, + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode, + const Word16 split_prerender_frame_size_ms ) +{ + Word32 bitrate; + + SWITCH( SplitRendBitRateId ) + { + case 4: + { + bitrate = SPLIT_REND_768k; + move32(); + BREAK; + } + case 3: + { + bitrate = SPLIT_REND_512k; + move32(); + BREAK; + } + case 2: + { + bitrate = SPLIT_REND_384k; + move32(); + BREAK; + } + case 1: + { + bitrate = SPLIT_REND_320k; + move32(); + BREAK; + } + case 0: + { + bitrate = SPLIT_REND_256k; + move32(); + BREAK; + } + default: + { + bitrate = -1; + move32(); + BREAK; + } + } + + bitrate = isar_get_lc3plus_bitrate( bitrate, poseCorrectionMode, split_prerender_frame_size_ms ); + + /* Return size in bytes */ + return (Word32) ( bitrate * split_prerender_frame_size_ms / 1000 / 8 ); +} +#endif + +/*------------------------------------------------------------------------- + * Function isar_split_rend_validate_config() + * + * + *------------------------------------------------------------------------*/ + +ivas_error isar_split_rend_validate_config( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const Word16 is_pcm_out ) +{ + /* Valid DOF range is 0-3 */ + test(); + IF( LT_16( pSplitRendConfig->dof, 0 ) || GT_16( pSplitRendConfig->dof, 3 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Valid DOF range is 0-3" ); + } + + /* Only CLDFB pose correction supports HQ mode */ + test(); + IF( NE_32( pSplitRendConfig->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) && NE_16( pSplitRendConfig->hq_mode, 0 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Only CLDFB pose correction supports HQ mode" ); + } + + /* Split rendering with no pose correction - 0 DOF and pose correction NONE must only ever be set together */ + test(); + test(); + test(); + IF( ( EQ_32( pSplitRendConfig->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) && NE_16( pSplitRendConfig->dof, 0 ) ) || + ( NE_32( pSplitRendConfig->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) && EQ_16( pSplitRendConfig->dof, 0 ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "0 DOF and pose correction NONE must only ever be set together" ); + } + + IF( NE_16( pSplitRendConfig->codec_frame_size_ms, 0 ) ) /* 0 means "default for current codec", will be set to actual value at a later stage */ + { + test(); + test(); + test(); + IF( EQ_32( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LCLD ) && NE_16( pSplitRendConfig->codec_frame_size_ms, 5 ) && NE_16( pSplitRendConfig->codec_frame_size_ms, 10 ) && NE_16( pSplitRendConfig->codec_frame_size_ms, 20 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Invalid framing for LCLD codec" ); + } + + test(); + test(); + IF( EQ_32( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) && NE_16( pSplitRendConfig->codec_frame_size_ms, 5 ) && NE_16( pSplitRendConfig->codec_frame_size_ms, 10 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Invalid framing for LC3plus codec" ); + } + } + + /* Validate bitrate */ + IF( EQ_16( is_pcm_out, 0 ) ) + { + SWITCH( pSplitRendConfig->splitRendBitRate ) + { + case SPLIT_REND_256k: + IF( NE_16( pSplitRendConfig->dof, 0 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Bitrates of 320 kbps and lower are only valid with 0 DOF" ); + } + BREAK; + case SPLIT_REND_320k: + /* Only valid with 0 DOF */ + IF( NE_16( pSplitRendConfig->dof, 0 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Bitrates of 320 kbps and lower are only valid with 0 DOF" ); + } + BREAK; + case SPLIT_REND_384k: + case SPLIT_REND_512k: +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + case SPLIT_REND_768k: +#endif + /* Always valid */ + BREAK; +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + case SPLIT_REND_768k: + test(); + IF( EQ_16( pSplitRendConfig->dof, 0 ) && EQ_32( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "Bitrate is too high for LC3plus with 0 DOF" ); + } + BREAK; +#endif + default: + return IVAS_ERR_LC3PLUS_INVALID_BITRATE; + } + } + ELSE + { + IF( EQ_16( pSplitRendConfig->dof, 1 ) ){ +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + IF( LT_32( pSplitRendConfig->splitRendBitRate, 34000 ) ){ + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "1DOF metadata needs atleast 34 kbps" ); + } +#else + IF( LT_32( pSplitRendConfig->splitRendBitRate, 50000 ) ){ + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "1DOF metadata needs atleast 50 kbps" ); + } +#endif +} +ELSE IF( EQ_16( pSplitRendConfig->dof, 2 ) ){ +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + IF( LT_32( pSplitRendConfig->splitRendBitRate, 50000 ) ){ + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "2DOF metadata needs atleast 50 kbps" ); +} +#else + IF( LT_32( pSplitRendConfig->splitRendBitRate, 66000 ) ){ + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "2DOF metadata needs atleast 66 kbps" ); +} +#endif +} +ELSE IF( EQ_16( pSplitRendConfig->dof, 3 ) ) +{ +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + IF( LT_32( pSplitRendConfig->splitRendBitRate, 82000 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "3DOF metadata needs atleast 128 kbps" ); + } +#else + IF( LT_32( pSplitRendConfig->splitRendBitRate, 128000 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SPLIT_REND_CONFIG, "3DOF metadata needs atleast 128 kbps" ); + } +#endif +} +} + +return IVAS_ERR_OK; +} + + +/*------------------------------------------------------------------------- + * Function isar_split_rend_get_quant_params() + * + * + *------------------------------------------------------------------------*/ + +void isar_split_rend_get_quant_params_fx( + const Word16 num_md_bands, + Word16 pred_real_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_imag_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_quant_pnts_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word32 pred_quantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word32 pred_1byquantstep_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 d_bands_yaw[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 bands_pitch[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_real_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], + Word16 pred_imag_bands_roll[ISAR_SPLIT_REND_NUM_QUANT_STRATS], +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + const Word16 ro_flag, +#endif + Word16 *num_quant_strats +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + , + Word16 *num_complex_bands +#endif +) +{ + Word16 q; + + *num_quant_strats = ISAR_SPLIT_REND_NUM_QUANT_STRATS; + move16(); +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + *num_complex_bands = COMPLEX_MD_BAND_THRESH_LOW; + move16(); + assert( *num_complex_bands <= num_md_bands ); +#endif + + pred_quant_pnts_yaw[0] = ISAR_SPLIT_REND_PRED_63QUANT_PNTS; + move16(); + pred_quantstep_yaw[0] = ISAR_SPLIT_REND_PRED63_Q_STEP_FX_Q31; + move32(); + pred_1byquantstep_yaw[0] = ISAR_SPLIT_REND_PRED63_1BYQ_STEP_FX_Q26; + move32(); + FOR( q = 1; q < *num_quant_strats; q++ ) + { + pred_quant_pnts_yaw[q] = ISAR_SPLIT_REND_PRED_31QUANT_PNTS; + move16(); + pred_quantstep_yaw[q] = ISAR_SPLIT_REND_PRED31_Q_STEP_FX_Q31; + move32(); + pred_1byquantstep_yaw[q] = ISAR_SPLIT_REND_PRED31_1BYQ_STEP_FX_Q26; + move32(); + } + + FOR( q = 0; q < *num_quant_strats; q++ ) + { + pred_real_bands_yaw[q] = num_md_bands; + move16(); + pred_real_bands_roll[q] = num_md_bands; + move16(); + } + +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + pred_imag_bands_yaw[0] = num_md_bands; + move16(); + pred_imag_bands_roll[0] = num_md_bands; + move16(); + pred_imag_bands_yaw[1] = num_md_bands; + move16(); + pred_imag_bands_roll[1] = num_md_bands; + move16(); + + FOR( q = 2; q < *num_quant_strats; q++ ) + { + pred_imag_bands_yaw[q] = LT_16( q, sub( *num_quant_strats, 1 ) ) ? num_md_bands : *num_complex_bands; + move16(); + pred_imag_bands_roll[q] = *num_complex_bands; + move16(); + } +#else + IF( ro_flag ) + { + FOR( q = 0; q < *num_quant_strats; q++ ) + { + pred_imag_bands_yaw[q] = SPLIT_REND_RO_MD_BAND_THRESH; + move16(); + } + } + ELSE + { + FOR( q = 0; q < *num_quant_strats - 2; q++ ) + { + pred_imag_bands_yaw[q] = num_md_bands; + move16(); + } + pred_imag_bands_yaw[( *num_quant_strats - 2 )] = COMPLEX_MD_BAND_THRESH_HIGH; + move16(); + pred_imag_bands_yaw[( *num_quant_strats - 1 )] = COMPLEX_MD_BAND_THRESH_LOW; + move16(); + } + + FOR( q = 0; q < *num_quant_strats; q++ ) + { + pred_imag_bands_roll[q] = SPLIT_REND_RO_MD_BAND_THRESH; + move16(); + } +#endif + + FOR( q = 0; q < *num_quant_strats; q++ ) + { + d_bands_yaw[q] = 0; + move16(); + bands_pitch[q] = num_md_bands; + move16(); + } + + return; +} + +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS +/*------------------------------------------------------------------------- + * Function isar_renderSplitGetRot_axisNumBits() + * + * + *------------------------------------------------------------------------*/ + +Word16 isar_renderSplitGetRot_axisNumBits( + const Word16 dof ) +{ + Word16 num_bits; + IF( dof < 3 ) + { + num_bits = 2; + } + ELSE + { + num_bits = 0; + } + return num_bits; +} + +/*------------------------------------------------------------------------- + * Function isar_renderSplitGetRot_axisFromCode() + * + * + *------------------------------------------------------------------------*/ + +ISAR_SPLIT_REND_ROT_AXIS isar_renderSplitGetRot_axisFromCode( + const Word16 dof, + const Word16 code ) +{ + ISAR_SPLIT_REND_ROT_AXIS rot_axis; + + IF( dof == 1 ) + { + rot_axis = (ISAR_SPLIT_REND_ROT_AXIS) code; + } + else if ( dof == 2 ) + { + IF( code == 0 ) + { + rot_axis = (ISAR_SPLIT_REND_ROT_AXIS) code; + } + ELSE + { + rot_axis = (ISAR_SPLIT_REND_ROT_AXIS) ( code - 1 ) + YAW_PITCH; + } + } + ELSE + { + rot_axis = (ISAR_SPLIT_REND_ROT_AXIS) DEFAULT_AXIS; + } + + return rot_axis; +} + +/*------------------------------------------------------------------------- + * Function isar_renderSplitGetCodeFromRot_axis() + * + * + *------------------------------------------------------------------------*/ + +Word16 isar_renderSplitGetCodeFromRot_axis( + const Word16 dof, + const ISAR_SPLIT_REND_ROT_AXIS rot_axis, + Word16 *num_bits ) +{ + Word16 code = 0; + IF( dof == 1 ) + { + code = (Word16) rot_axis; + } + else if ( dof == 2 ) + { + IF( rot_axis == DEFAULT_AXIS ) + { + code = (Word16) rot_axis; + } + ELSE + { + code = (Word16) ( rot_axis - YAW_PITCH ) + 1; + } + } + ELSE + { + code = (Word16) DEFAULT_AXIS; + } + *num_bits = isar_renderSplitGetRot_axisNumBits( dof ); + + return code; +} +#endif + +/*------------------------------------------------------------------------- + * Function isar_renderSplitGetMultiBinPoseData() + * + * + *------------------------------------------------------------------------*/ + +void isar_renderSplitGetMultiBinPoseData_fx( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const ISAR_SPLIT_REND_ROT_AXIS rot_axis ) +{ + Word16 pos_idx, num_yaw_poses, num_pitch_poses, num_roll_poses; + const Word32 *relative_yaw_angles; + const Word32 *relative_pitch_angles; + const Word32 *relative_roll_angles; + + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] = 0; + move32(); + pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] = 0; + move32(); + pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] = 0; + move32(); + } + + /* 0 DOF defaults */ + num_yaw_poses = 0; + move16(); + num_pitch_poses = 0; + move16(); + num_roll_poses = 0; + move16(); + + /* defaults for all DOF except 3DOF HQ */ + relative_yaw_angles = ivas_split_rend_relative_yaw_pos_angles_hq_fx; + relative_pitch_angles = ivas_split_rend_relative_pitch_pos_angles_hq_fx; + relative_roll_angles = ivas_split_rend_relative_roll_pos_angles_hq_fx; + + IF( EQ_16( pSplit_rend_config->dof, 1 ) ) + { + SWITCH( rot_axis ) + { + case DEFAULT_AXIS: + case YAW: + { + num_yaw_poses = SPLIT_REND_MAX_YAW_ONLY_POSES; + move16(); + BREAK; + } + case PITCH: + { + num_pitch_poses = SPLIT_REND_MAX_PITCH_ONLY_POSES; + move16(); + BREAK; + } + case ROLL: + { + num_roll_poses = SPLIT_REND_MAX_ROLL_ONLY_POSES; + move16(); + BREAK; + } + default: + { + assert( 0 && "unsupported rotation axis value" ); + } + } + } + ELSE IF( EQ_16( pSplit_rend_config->dof, 2 ) ) + { + SWITCH( rot_axis ) + { + case DEFAULT_AXIS: +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + case YAW: + case PITCH: +#endif + case YAW_PITCH: + { + num_yaw_poses = SPLIT_REND_MAX_YAW_ONLY_POSES; + move16(); + num_pitch_poses = SPLIT_REND_MAX_PITCH_ONLY_POSES; + move16(); + BREAK; + } +#ifndef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + case ROLL: +#endif + case YAW_ROLL: + { + num_yaw_poses = SPLIT_REND_MAX_YAW_ONLY_POSES; + move16(); + num_roll_poses = SPLIT_REND_MAX_ROLL_ONLY_POSES; + move16(); + BREAK; + } + case PITCH_ROLL: + { + num_pitch_poses = SPLIT_REND_MAX_PITCH_ONLY_POSES; + move16(); + num_roll_poses = SPLIT_REND_MAX_ROLL_ONLY_POSES; + move16(); + BREAK; + } + default: + { + assert( 0 && "unsupported rotation axis value" ); + } + } + } + ELSE IF( EQ_16( pSplit_rend_config->dof, 3 ) ) + { + IF( EQ_16( pSplit_rend_config->hq_mode, 1 ) ) + { + relative_yaw_angles = ivas_split_rend_relative_yaw_pos_angles_hq_fx; + relative_pitch_angles = ivas_split_rend_relative_pitch_pos_angles_hq_fx; + relative_roll_angles = ivas_split_rend_relative_roll_pos_angles_hq_fx; + num_yaw_poses = SPLIT_REND_MAX_YAW_ONLY_POSES; + move16(); + num_pitch_poses = SPLIT_REND_MAX_PITCH_ONLY_POSES; + move16(); + num_roll_poses = SPLIT_REND_MAX_ROLL_ONLY_POSES; + move16(); + } + ELSE + { + relative_yaw_angles = ivas_split_rend_relative_yaw_pos_angles_fx; + relative_pitch_angles = ivas_split_rend_relative_pitch_pos_angles_fx; + relative_roll_angles = ivas_split_rend_relative_roll_pos_angles_fx; + num_yaw_poses = SPLIT_REND_MAX_YAW_ONLY_POSES; + move16(); + num_pitch_poses = 1; + move16(); + num_roll_poses = 1; + move16(); + } + } + + pMultiBinPoseData->num_poses = add( add( num_yaw_poses, num_pitch_poses ), add( num_roll_poses, 1 ) ); + assert( LE_16( pMultiBinPoseData->num_poses, MAX_HEAD_ROT_POSES ) ); + + FOR( pos_idx = 0; pos_idx < num_yaw_poses; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses_fx[pos_idx + 1][0] = relative_yaw_angles[pos_idx]; + move32(); + } + + FOR( pos_idx = 0; pos_idx < num_pitch_poses; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses_fx[pos_idx + num_yaw_poses + 1][1] = relative_pitch_angles[pos_idx]; + move32(); + } + + FOR( pos_idx = 0; pos_idx < num_roll_poses; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses_fx[pos_idx + num_yaw_poses + num_pitch_poses + 1][2] = relative_roll_angles[pos_idx]; + move32(); + } + pMultiBinPoseData->dof = pSplit_rend_config->dof; + move16(); + pMultiBinPoseData->hq_mode = pSplit_rend_config->hq_mode; + move16(); + pMultiBinPoseData->rot_axis = rot_axis; + move32(); + pMultiBinPoseData->poseCorrectionMode = pSplit_rend_config->poseCorrectionMode; + move32(); + + return; +} + +/*------------------------------------------------------------------------- + * Function isar_renderSplitUpdateNoCorrectionPoseData() + * + * + *------------------------------------------------------------------------*/ + +void isar_renderSplitUpdateNoCorrectionPoseData( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + pMultiBinPoseData->num_poses = 1; + move16(); + assert( pSplit_rend_config->dof == 0 ); + pMultiBinPoseData->dof = pSplit_rend_config->dof; + move16(); + assert( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ); + pMultiBinPoseData->poseCorrectionMode = pSplit_rend_config->poseCorrectionMode; + move32(); + + return; +} + + +/*------------------------------------------------------------------------- + * Function isar_init_multi_bin_pose_data() + * + * + *------------------------------------------------------------------------*/ + +void isar_init_multi_bin_pose_data_fx( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + Word16 pos_idx; + + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] = 0; + move32(); + pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] = 0; + move32(); + pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] = 0; + move32(); + } + pMultiBinPoseData->num_poses = 1; + move16(); + pMultiBinPoseData->dof = 3; + move16(); + pMultiBinPoseData->hq_mode = 0; + move16(); + pMultiBinPoseData->rot_axis = DEFAULT_AXIS; + move32(); + + return; +} + +/* Copy for encoder, to be removed */ +void isar_init_multi_bin_pose_data_fx_enc( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + Word16 pos_idx; + + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] = 0; + move32(); + pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] = 0; + move32(); + pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] = 0; + move32(); + } + pMultiBinPoseData->num_poses = 1; + move16(); + pMultiBinPoseData->dof = 3; + move16(); + pMultiBinPoseData->hq_mode = 0; + move16(); + pMultiBinPoseData->rot_axis = DEFAULT_AXIS; + move32(); + + return; +} +void isar_init_multi_bin_pose_data( + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) +{ + int16_t pos_idx; + + for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + pMultiBinPoseData->relative_head_poses[pos_idx][0] = 0.0f; + pMultiBinPoseData->relative_head_poses[pos_idx][1] = 0.0f; + pMultiBinPoseData->relative_head_poses[pos_idx][2] = 0.0f; + } + pMultiBinPoseData->num_poses = 1; + pMultiBinPoseData->dof = 3; + pMultiBinPoseData->hq_mode = 0; + pMultiBinPoseData->rot_axis = DEFAULT_AXIS; + + return; +} + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +ivas_error isar_framesize_to_ms( + const IVAS_RENDER_FRAMESIZE frame_size, /* i : frame size enum */ + int16_t *ms /* o : frame size in ms */ +) +{ + switch ( frame_size ) + { + case IVAS_RENDER_FRAMESIZE_5MS: + *ms = 5; + break; + case IVAS_RENDER_FRAMESIZE_10MS: + *ms = 10; + break; + case IVAS_RENDER_FRAMESIZE_20MS: + *ms = 20; + break; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL, "Unsupported ISAR frame size" ); + } + + return IVAS_ERR_OK; +} +#endif + +/*------------------------------------------------------------------------- + * Function isar_split_rend_choose_default_codec() + * + * + *------------------------------------------------------------------------*/ + +ivas_error isar_split_rend_choose_default_codec( + ISAR_SPLIT_REND_CODEC *pCodec, /* i/o: pointer to codec setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t *pIsar_frame_size_ms, /* i/o: pointer to isar frame size setting */ +#endif + Word16 *pCodec_frame_size_ms, /* i/o: pointer to codec frame size setting */ + const Word16 cldfb_in_flag, /* i : flag indicating rendering in TD */ + const Word16 pcm_out_flag, /* i : flag to indicate PCM output */ + const Word16 num_subframes /* i : number of subframes */ +) +{ + IF( EQ_16( pcm_out_flag, 0 ) ) + { + IF( EQ_32( *pCodec, ISAR_SPLIT_REND_CODEC_DEFAULT ) ) + { + *pCodec = cldfb_in_flag ? ISAR_SPLIT_REND_CODEC_LCLD : ISAR_SPLIT_REND_CODEC_LC3PLUS; + move32(); + } + } + ELSE + { + *pCodec = ISAR_SPLIT_REND_CODEC_NONE; + move32(); + } + + IF( EQ_16( *pCodec_frame_size_ms, 0 ) ) /* codec frame size hasn't been set yet - use default for current configuration */ + { + SWITCH( *pCodec ) + { + case ISAR_SPLIT_REND_CODEC_LCLD: + *pCodec_frame_size_ms = DEPR_i_mult( num_subframes, 5 ); + BREAK; + case ISAR_SPLIT_REND_CODEC_LC3PLUS: + case ISAR_SPLIT_REND_CODEC_NONE: + *pCodec_frame_size_ms = 5; + move16(); + BREAK; + default: + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unknown split codec value" ); + } + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + IF( *pIsar_frame_size_ms == 0 ) /* isar frame size hasn't been set yet - use default for current configuration */ + { + *pIsar_frame_size_ms = 20; + } +#endif + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * Function get_bit() + * + * + *-------------------------------------------------------------------*/ + +Word32 get_bit( + const Word32 state, + const Word32 bit_id ) +{ + return L_and( state, ( L_shl( 1, (Word16) bit_id ) ) ); +} + +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 < N; i++ ) + { + y[i] = a; + } + + return; +} + +void set32_fx( + Word32 y[], /* i/o: Vector to set */ + const Word32 a, /* i : Value to set the vector to */ + const Word16 N /* i : Length of the vector */ +) +{ + Word16 i; + + FOR( i = 0; i < N; i++ ) + { + y[i] = a; + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * ceil_log_2() + * + * calculates ceil(log2(val)) + *-------------------------------------------------------------------*/ + +Word16 ceil_log_2( + UWord64 val ) +{ + + IF( val <= 0 ) + { + assert( 0 ); + } + return val <= 1 ? 0 : val <= 2 ? 1 + : val <= 4 ? 2 + : val <= 8 ? 3 + : val <= 16 ? 4 + : val <= 32 ? 5 + : val <= 64 ? 6 + : val <= 128 ? 7 + : val <= 256 ? 8 + : val <= 512 ? 9 + : val <= 1024 ? 10 + : val <= 2048 ? 11 + : val <= 4096 ? 12 + : val <= 8192 ? 13 + : val <= 16384 ? 14 + : val <= 32768 ? 15 + : val <= 65536 ? 16 + : val <= 131072 ? 17 + : val <= 262144 ? 18 + : val <= 524288 ? 19 + : val <= 1048576 ? 20 + : val <= 2097152 ? 21 + : val <= 4194304 ? 22 + : val <= 8388608 ? 23 + : val <= 16777216 ? 24 + : val <= 33554432 ? 25 + : val <= 67108864 ? 26 + : val <= 134217728 ? 27 + : val <= 268435456 ? 28 + : val <= 536870912 ? 29 + : val <= 1073741824 ? 30 + : val <= 2147483648 ? 31 + : val <= 4294967296 ? 32 + : val <= 8589934592 ? 33 + : val <= 17179869184 ? 34 + : val <= 34359738368 ? 35 + : val <= 68719476736 ? 36 + : val <= 137438953472 ? 37 + : val <= 274877906944 ? 38 + : val <= 549755813888 ? 39 + : val <= 1099511627776 ? 40 + : val <= 2199023255552 ? 41 + : val <= 4398046511104 ? 42 + : val <= 8796093022208 ? 43 + : val <= 17592186044416 ? 44 + : val <= 35184372088832 ? 45 + : val <= 70368744177664 ? 46 + : val <= 140737488355328 ? 47 + : val <= 281474976710656 ? 48 + : val <= 562949953421312 ? 49 + : val <= 1125899906842624 ? 50 + : val <= 2251799813685248 ? 51 + : val <= 4503599627370496 ? 52 + : val <= 9007199254740992 ? 53 + : val <= 18014398509481984 ? 54 + : val <= 36028797018963968 ? 55 + : val <= 72057594037927936 ? 56 + : val <= 144115188075855872 ? 57 + : val <= 288230376151711744 ? 58 + : val <= 576460752303423488 ? 59 + : val <= 1152921504606846976 ? 60 + : val <= 2305843009213693952 ? 61 + : val <= 4611686018427387904 ? 62 + : val <= 9223372036854775807 ? 63 + : 64; +} +#endif diff --git a/lib_isar/isar_stat.h b/lib_isar/isar_stat.h new file mode 100644 index 000000000..e94d23e18 --- /dev/null +++ b/lib_isar/isar_stat.h @@ -0,0 +1,267 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef ISAR_STAT_H +#define ISAR_STAT_H + + +#include +#include "options.h" +#include "stat_com.h" +#include "ivas_stat_com.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include "isar_lcld_prot.h" +#include "isar_lc3plus_enc.h" +#include "isar_lc3plus_dec.h" +#include "isar_cnst.h" + + +/*-------------------------------------------------------------------* + * ISAR post rend constants + *-------------------------------------------------------------------*/ + +#define MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL ( MAX_BUFFER_LENGTH_PER_CHANNEL * 2 ) +#define MAX_CLDFB_BUFFER_LENGTH ( MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) +#define MAX_BIN_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * BINAURAL_CHANNELS ) +#define MAX_CLDFB_BIN_BUFFER_LENGTH ( MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL * BINAURAL_CHANNELS ) + +/*-------------------------------------------------------------------* + * ISAR post rend structs + *-------------------------------------------------------------------*/ + +typedef struct +{ + int8_t headRotEnabled; + IVAS_QUATERNION headPositions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + IVAS_VECTOR3 Pos[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 crossfade_fx[L_FRAME48k / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis; + +} ISAR_POST_REND_HeadRotData; + +typedef struct +{ +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + HANDLE_CLDFB_FILTER_BANK cldfbAna[( 1 + MAX_HEAD_ROT_POSES ) * BINAURAL_CHANNELS]; +#else + HANDLE_CLDFB_FILTER_BANK cldfbAna[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; +#endif + HANDLE_CLDFB_FILTER_BANK cldfbSyn[BINAURAL_CHANNELS]; + +} CLDFB_HANDLES_WRAPPER, *CLDFB_HANDLES_WRAPPER_HANDLE; + +typedef struct isar_split_rend_huffman_cfg_t +{ + const int32_t *codebook; + int16_t min_len; + int16_t max_len; + int16_t sym_len; + +} isar_split_rend_huffman_cfg_t; + +typedef struct isar_binaural_head_rot_split_rendering_huff_struct +{ + isar_split_rend_huffman_cfg_t pred[2]; + int16_t pred_idx_trav[2][ISAR_SPLIT_REND_PRED_63QUANT_PNTS]; + int16_t pred_base2_code_len[2]; + isar_split_rend_huffman_cfg_t pred_roll; + int16_t pred_roll_idx_trav[ISAR_SPLIT_REND_ROLL_PRED_QUANT_PNTS]; + int16_t pred_roll_base2_code_len; + isar_split_rend_huffman_cfg_t gd; + int16_t gd_base2_code_len; + int16_t gd_idx_trav[ISAR_SPLIT_REND_D_QUANT_PNTS]; + isar_split_rend_huffman_cfg_t p_gd; + int16_t p_gd_base2_code_len; + int16_t p_gd_idx_trav[ISAR_SPLIT_REND_D_QUANT_PNTS]; + isar_split_rend_huffman_cfg_t p_gd_diff; + int16_t p_gd_diff_base2_code_len; + int16_t p_gd_diff_idx_trav[ISAR_SPLIT_REND_D_QUANT_PNTS]; + +} ISAR_BIN_HR_SPLIT_REND_HUFF, *ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE; + +/* binaural split rendering head rotation data structure */ +typedef struct isar_binaural_head_rot_split_rendering_md_struct +{ + Word32 pred_mat_re_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Q25 */ + Word16 exp_pred_mat_re; + Word32 pred_mat_im_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Q25 */ + Word16 exp_pred_mat_im; +#ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS + Word32 pred_mat_re2[BINAURAL_CHANNELS]; + Word16 exp_pred_mat_re2; +#endif + Word32 gd_fx; /* Q25 */ + Word32 gd2_fx; /* Q25 */ + Word16 exp_gd; + Word16 exp_gd2; + int16_t pred_mat_re_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + int16_t pred_mat_im_idx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + int16_t gd_idx; + int16_t gd2_idx; + +} ISAR_BIN_HR_SPLIT_REND_MD, *ISAR_BIN_HR_SPLIT_REND_MD_HANDLE; +typedef struct isar_binaural_head_rot_split_pre_rendering_struct +{ + ISAR_BIN_HR_SPLIT_REND_MD rot_md[MAX_HEAD_ROT_POSES - 1][MAX_SPLIT_MD_SUBFRAMES][MAX_SPLIT_REND_MD_BANDS]; + Word32 fix_pos_rot_mat_fx[MAX_HEAD_ROT_POSES - 1][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + float fix_pos_rot_mat[MAX_HEAD_ROT_POSES - 1][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1]; + ISAR_BIN_HR_SPLIT_REND_HUFF huff_cfg; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + HANDLE_CLDFB_FILTER_BANK cldfbSynRotBinDec[MAX_HEAD_ROT_POSES + 1][BINAURAL_CHANNELS]; +#endif + +#ifdef SPLIT_POSE_CORRECTION_DEBUG + BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend; +#endif + +} ISAR_BIN_HR_SPLIT_PRE_REND, *ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE; +/*----------------------------------------------------------------------------------* + * Output configuration for renderer (e.g. DirAC, MASA, Binaural Renderer...) + *----------------------------------------------------------------------------------*/ + +typedef struct isar_binaural_head_rot_split_rendering_lcld_enc_struct +{ + void *pLcld_enc; + Word16 iChannels; + LCLDEncoder *psLCLDEncoder; + Word32 ***pppfLCLDReal_fx; + Word32 ***pppfLCLDImag_fx; +#ifdef CLDFB_DEBUG + FILE *cldfbIn; + int16_t numFrame; +#endif + Word16 iNumIterations; + Word16 iNumBlocks; + +} ISAR_BIN_HR_SPLIT_LCLD_ENC, *ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE; + +typedef struct +{ + Word32 Cldfb_Prev_BinReal_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX + CLDFB_PLC_XF][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_Prev_BinImag_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX + CLDFB_PLC_XF][CLDFB_NO_CHANNELS_MAX]; + Word16 Q_Prev_Bin_fx; + Word32 xf_bet_fx[2][CLDFB_NO_CHANNELS_MAX][CLDFB_PLC_XF]; + +} ISAR_CLDFB_PLC, *ISAR_CLDFB_PLC_HANDLE; +typedef struct +{ + ISAR_CLDFB_PLC CldfbPLC_state; + Word16 prev_bfi; + Word16 bf_count; + Word16 iNumSubSets; + +} ISAR_SPLIT_REND_PLC_STRUCT, *ISAR_SPLIT_REND_PLC_HANDLE; +typedef struct isar_binaural_head_rot_split_rendering_lcld_dec_struct +{ + void *pLcld_dec; + Word32 iChannels; + LCLDDecoder *psLCLDDecoder; + Word32 ***pppfDecLCLDReal_fx; + Word32 ***pppfDecLCLDImag_fx; +#ifdef CLDFB_DEBUG + FILE *cldfbOut; + int16_t numFrame; +#endif + ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC; + + Word16 iNumBlocks; + Word16 iNumIterations; + +} ISAR_BIN_HR_SPLIT_LCLD_DEC, *ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE; +typedef struct isar_binaural_head_rot_split_post_rendering_struct +{ + ISAR_BIN_HR_SPLIT_REND_MD rot_md[MAX_HEAD_ROT_POSES][MAX_SPLIT_MD_SUBFRAMES][MAX_SPLIT_REND_MD_BANDS]; + IVAS_QUATERNION QuaternionsPre[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t low_Res; + + float fix_pos_rot_mat[MAX_HEAD_ROT_POSES - 1][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 fix_pos_rot_mat_fx[MAX_HEAD_ROT_POSES - 1][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Q31 */ + ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1]; + ISAR_BIN_HR_SPLIT_REND_HUFF huff_cfg; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + Word32 mixer_mat_re_fx[MAX_HEAD_ROT_POSES][MAX_SPLIT_REND_MD_BANDS][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mixer_mat_im_fx[MAX_HEAD_ROT_POSES][MAX_SPLIT_REND_MD_BANDS][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 gd_mem_fx[MAX_HEAD_ROT_POSES][MAX_SPLIT_REND_MD_BANDS]; +#else + Word32 mixer_mat_re_fx[1][MAX_SPLIT_REND_MD_BANDS][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 mixer_mat_im_fx[1][MAX_SPLIT_REND_MD_BANDS][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; + Word32 gd_mem_fx[1][MAX_SPLIT_REND_MD_BANDS]; +#endif + int16_t cf_flag; + HANDLE_CLDFB_FILTER_BANK cldfbAna[BINAURAL_CHANNELS]; + HANDLE_CLDFB_FILTER_BANK cldfbSyn[BINAURAL_CHANNELS]; +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + HANDLE_CLDFB_FILTER_BANK cldfbSynReconsBinDec[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS]; +#endif + +} ISAR_BIN_HR_SPLIT_POST_REND, *ISAR_BIN_HR_SPLIT_POST_REND_HANDLE; + +typedef struct +{ + int16_t num_poses; + float relative_head_poses[MAX_HEAD_ROT_POSES][3]; + Word32 relative_head_poses_fx[MAX_HEAD_ROT_POSES][3]; /* Q22 */ + int16_t dof; + int16_t hq_mode; + ISAR_SPLIT_REND_ROT_AXIS rot_axis; + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrectionMode; + +} MULTI_BIN_REND_POSE_DATA; + +typedef struct +{ + MULTI_BIN_REND_POSE_DATA multiBinPoseData; + ISAR_BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend; + ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec; + int16_t first_good_frame_received; + ISAR_LC3PLUS_DEC_HANDLE hLc3plusDec; + +} ISAR_SPLIT_POST_REND_WRAPPER; + + +typedef struct +{ + MULTI_BIN_REND_POSE_DATA multiBinPoseData; + ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend; + ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc; + CLDFB_HANDLES_WRAPPER_HANDLE hCldfbHandles; + ISAR_LC3PLUS_ENC_HANDLE hLc3plusEnc; + float *lc3plusDelayBuffers[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* Used to time-align head pose correction metadata with LC3plus-coded reference audio */ + Word32 *lc3plusDelayBuffers_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* Used to time-align head pose correction metadata with LC3plus-coded reference audio */ + Word16 lc3plusDelayBuffers_q; + Word32 lc3plusDelaySamples; +} SPLIT_REND_WRAPPER; + +#endif + +#endif /* ISAR_STAT_H */ diff --git a/lib_isar/lib_isar_post_rend.c b/lib_isar/lib_isar_post_rend.c new file mode 100644 index 000000000..178718a60 --- /dev/null +++ b/lib_isar/lib_isar_post_rend.c @@ -0,0 +1,1913 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + + +#include "options.h" +#include "lib_isar_post_rend.h" +#include "isar_stat.h" +#include "isar_prot.h" +#include "prot.h" +#include "ivas_prot.h" +#include "prot_fx2.h" +#ifndef SPLIT_REND_WITH_HEAD_ROT + +int32_t ISAR_POST_REND_void_func( void ) +{ + return 0; +} + +#else + +#include "ivas_prot_rend.h" +#include +#include +#include "wmc_auto.h" +#include "prot_fx2.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * Local types + *-------------------------------------------------------------------*/ + +/* EFAP wrapper to simplify writing panning gains to a vector that includes LFE channels */ +typedef struct +{ + EFAP_HANDLE hEfap; + AUDIO_CONFIG speakerConfig; + const LSSETUP_CUSTOM_STRUCT *pCustomLsSetup; /* Pointer to main custom LS struct from renderer handle - doesn't need freeing */ +} EFAP_WRAPPER; + +/* Lightweight helper struct that gathers all information required for rendering + * any config to any other config. Used to simplify signatures of rendering functions. + * + * This struct should store ONLY CONST POINTERS to data existing elsewhere. + * Storing pointers instead of data itself ensures that no additional updates + * are required when any of these are changed in the renderer. Making the pointers + * const ensures that this data is only read, but not modified by the rendering functions. */ +typedef struct +{ + const int32_t *pOutSampleRate; + const AUDIO_CONFIG *pOutConfig; +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + const LSSETUP_CUSTOM_STRUCT *pCustomLsOut; + const EFAP_WRAPPER *pEfapOutWrapper; +#endif + const ISAR_POST_REND_HeadRotData *pHeadRotData; +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + const RENDER_CONFIG_HANDLE *hhRendererConfig; +#endif + const int16_t *pSplitRendBFI; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const ISAR_SPLIT_REND_CONFIG_DATA *pSplitRenderConfig; +#endif +} rendering_context; + +/* Common base for input structs */ +typedef struct +{ + AUDIO_CONFIG inConfig; + ISAR_POST_REND_InputId id; + IVAS_REND_AudioBuffer inputBuffer; + Word32 gain_fx; /* Linear, not in dB */ + rendering_context ctx; + int32_t numNewSamplesPerChannel; /* Used to keep track how much new audio was fed before rendering current frame */ +} input_base; + +typedef struct +{ + input_base base; + ISAR_SPLIT_POST_REND_WRAPPER splitPostRendWrapper; + Word32 *bufferData_fx; + int16_t numCachedSamples; /* Number of decoded samples in bufferData that have not yet been played out */ + ISAR_POST_REND_BitstreamBuffer *hBits; +} input_split_post_rend; + +struct ISAR_POST_REND +{ + int32_t sampleRateOut; + + IVAS_LIMITER_HANDLE hLimiter; +#ifdef DEBUGGING + int32_t numClipping; /* Counter of clipped output samples */ +#endif + + input_split_post_rend inputsSplitPost[RENDERER_MAX_BIN_INPUTS]; + + AUDIO_CONFIG inputConfig; + AUDIO_CONFIG outputConfig; + + ISAR_POST_REND_HeadRotData headRotData; + int16_t splitRendBFI; + + int8_t rendererConfigEnabled; + ISAR_SPLIT_REND_CONFIG_DATA splitRenderConfig; + + int16_t num_subframes; +}; + +/*-------------------------------------------------------------------* + * getAudioConfigType() + * + * + *-------------------------------------------------------------------*/ +ISAR_POST_REND_AudioConfigType isar_getAudioConfigType( + const AUDIO_CONFIG config ) +{ + ISAR_POST_REND_AudioConfigType type; + + SWITCH( config ) + { + case IVAS_AUDIO_CONFIG_BINAURAL: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + type = ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL; + BREAK; + default: + type = ISAR_POST_REND_AUDIO_CONFIG_TYPE_UNKNOWN; + BREAK; + } + + return type; +} + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ +static ivas_error allocateInputBaseBufferData_fx( + Word32 **data, + const Word16 data_size ) +{ + *data = (Word32 *) malloc( data_size * sizeof( Word32 ) ); + IF( *data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for input base buffer data" ); + } + + return IVAS_ERR_OK; +} +static void freeInputBaseBufferData_fx( + Word32 **data ) +{ + IF( *data != NULL ) + { + free( *data ); + *data = NULL; + } + + return; +} + +static IVAS_QUATERNION quaternionInit( + void ) +{ + IVAS_QUATERNION q; + q.w_fx = ONE_IN_Q22; + q.x_fx = q.y_fx = q.z_fx = 0; + return q; +} + +static void convertBitsBufferToInternalBitsBuff( + const ISAR_POST_REND_BitstreamBuffer outBits, + ISAR_SPLIT_REND_BITS_HANDLE hBits ) +{ + hBits->bits_buf = outBits.bits; + hBits->bits_read = outBits.config.bitsRead; + hBits->bits_written = outBits.config.bitsWritten; + hBits->buf_len = outBits.config.bufLenInBytes; + hBits->codec = outBits.config.codec; + hBits->pose_correction = outBits.config.poseCorrection; + hBits->codec_frame_size_ms = outBits.config.codec_frame_size_ms; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hBits->isar_frame_size_ms = outBits.config.isar_frame_size_ms; + hBits->lc3plus_highres = outBits.config.lc3plusHighRes; +#endif + + return; +} + +static void convertInternalBitsBuffToBitsBuffer( + ISAR_POST_REND_BitstreamBuffer *hOutBits, + const ISAR_SPLIT_REND_BITS_DATA bits ) +{ + hOutBits->bits = bits.bits_buf; + hOutBits->config.bitsRead = bits.bits_read; + hOutBits->config.bitsWritten = bits.bits_written; + hOutBits->config.bufLenInBytes = bits.buf_len; + hOutBits->config.codec = bits.codec; + hOutBits->config.poseCorrection = bits.pose_correction; + hOutBits->config.codec_frame_size_ms = bits.codec_frame_size_ms; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hOutBits->config.isar_frame_size_ms = bits.isar_frame_size_ms; + hOutBits->config.lc3plusHighRes = bits.lc3plus_highres; +#endif + + return; +} + +static void copyBufferTo2dArray_fx( + const IVAS_REND_AudioBuffer buffer, + Word32 array[][L_FRAME48k] ) +{ + UWord32 smplIdx; + UWord32 chnlIdx; + const Word32 *readPtr; + + assert( ( buffer.config.is_cldfb == 0 ) && "for CLDFB input call copyBufferToCLDFBarray()" ); + readPtr = buffer.data_fx; + + FOR( chnlIdx = 0; chnlIdx < (UWord32) buffer.config.numChannels; ++chnlIdx ) + { + FOR( smplIdx = 0; smplIdx < (UWord32) buffer.config.numSamplesPerChannel; ++smplIdx ) + { + array[chnlIdx][smplIdx] = *readPtr++; + } + } + + return; +} + +static void accumulate2dArrayToBuffer_fx( + Word32 array[][L_FRAME48k], + Word16 Q_out[][BINAURAL_CHANNELS], + Word16 Q_max, + const IVAS_REND_AudioBuffer *buffer, + Word16 num_subframes, + Word16 subframe_length ) +{ + Word16 smplIdx, chnlIdx; + Word32 *writePtr; + + writePtr = buffer->data_fx; + FOR( chnlIdx = 0; chnlIdx < buffer->config.numChannels; ++chnlIdx ) + { + FOR( Word16 sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( smplIdx = 0; smplIdx < subframe_length; ++smplIdx ) + { + //*writePtr++ += (float) array[chnlIdx][( sf_idx * subframe_length ) + smplIdx] / powf( 2, Q_out[sf_idx][chnlIdx] ); + *writePtr++ += L_shl( array[chnlIdx][( sf_idx * subframe_length ) + smplIdx], sub( Q_max, Q_out[sf_idx][chnlIdx] ) ); + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * limitRendererOutput() + * + * In-place saturation control for multichannel buffers with adaptive release time + *-------------------------------------------------------------------*/ + +#ifndef DISABLE_LIMITER +/*! r: number of clipped output samples */ +static Word32 limitRendererOutput_fx( + IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ + Word32 *output, /* i/o: I/O buffer */ + const Word16 output_frame, /* i : number of samples per channel in the buffer */ + const Word32 threshold, /* i : signal amplitude above which limiting starts to be applied */ + Word16 q_factor ) /* i : q factor of output samples */ +{ + Word16 i; + Word32 **channels; + Word16 num_channels; + Word32 numClipping = 0; + + /* return early if given bad parameters */ + IF( hLimiter == NULL || output == NULL || output_frame <= 0 ) + { + return 0; + } + + channels = hLimiter->channel_ptrs_fx; + num_channels = hLimiter->num_channels; + + FOR( i = 0; i < num_channels; ++i ) + { + channels[i] = output + i * output_frame; + } + + limiter_process_fx( hLimiter, output_frame, threshold, 0, NULL, q_factor ); + + /* Apply clipping to buffer in case the limiter let through some samples > 1.0f */ + FOR( i = 0; i < output_frame * num_channels; ++i ) + { + + output[i] = min( max( L_shl( INT16_MIN, q_factor ), output[i] ), L_shl( INT16_MAX, q_factor ) ); + } + + return numClipping; +} + +#endif + + +/*-------------------------------------------------------------------* + * validateOutputSampleRate() + * + * + *-------------------------------------------------------------------*/ +static ivas_error validateOutputSampleRate( + const Word32 sampleRate, + const AUDIO_CONFIG outConfig ) +{ + IF( ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && NE_32( sampleRate, 48000 ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Error: Only 48kHz output sampling rate is supported for split rendering." ); + } + ELSE + { + /* Otherwise rendering to binaural, support the same set as IVAS decoder */ + SWITCH( sampleRate ) + { + case 8000: + case 16000: + case 32000: + case 48000: + return IVAS_ERR_OK; + } + + return IVAS_ERR_INVALID_SAMPLING_RATE; + } +} + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ +static ivas_error initLimiter( + IVAS_LIMITER_HANDLE *phLimiter, + const Word16 numChannels, + const Word32 sampleRate ) +{ + ivas_error error; + + /* If re-initializing with unchanged values, return early */ + IF( *phLimiter != NULL && ( *phLimiter )->num_channels == numChannels && ( *phLimiter )->sampling_rate == sampleRate ) + { + return IVAS_ERR_OK; + } + + /* Support re-init: close if already allocated */ + IF( *phLimiter != NULL ) + { + ivas_limiter_close_splitRend( phLimiter ); + } + + IF( ( error = ivas_limiter_open_splitRend( phLimiter, numChannels, sampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static ivas_error initHeadRotation( + ISAR_POST_REND_HANDLE hIvasRend ) +{ + Word16 i, crossfade_len; + Word32 tmp; + + /* Head rotation is enabled by default */ + hIvasRend->headRotData.headRotEnabled = 1; + + /* Initialize 5ms crossfade */ + crossfade_len = 240 /*L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES*/; + tmp = 8985287 /*1.f / ( crossfade_len - 1 )*/; + FOR( i = 0; i < crossfade_len; i++ ) + { + hIvasRend->headRotData.crossfade_fx[i] = W_extract_l( W_mult0_32_32( i, tmp ) ); + } + + /* Initialize with unit quaternions */ + FOR( i = 0; i < hIvasRend->num_subframes; ++i ) + { + hIvasRend->headRotData.headPositions[i] = quaternionInit(); + } + + hIvasRend->headRotData.sr_pose_pred_axis = DEFAULT_AXIS; + + return IVAS_ERR_OK; +} +static void initRendInputBase_fx( + input_base *inputBase, + const AUDIO_CONFIG inConfig, + const IVAS_REND_InputId id, + const rendering_context rendCtx, + Word32 *dataBuf, + const Word16 dataBufSize ) +{ + inputBase->inConfig = inConfig; + inputBase->id = id; + inputBase->gain_fx = MAX_32; + inputBase->ctx = rendCtx; + inputBase->numNewSamplesPerChannel = 0; + + inputBase->inputBuffer.config.numSamplesPerChannel = 0; + inputBase->inputBuffer.config.numChannels = 0; + inputBase->inputBuffer.data_fx = dataBuf; + IF( inputBase->inputBuffer.data_fx != NULL ) + { + set_l( inputBase->inputBuffer.data_fx, 0, dataBufSize ); + } + + return; +} + +static rendering_context getRendCtx( + ISAR_POST_REND_HANDLE hIvasRend ) +{ + rendering_context ctx; + + /* Note: when refactoring this, always take the ADDRESS of a member of the + * renderer struct, so that the context stores a POINTER to the member, even + * if the member is a pointer or handle itself. */ + ctx.pOutConfig = &hIvasRend->outputConfig; + ctx.pOutSampleRate = &hIvasRend->sampleRateOut; + ctx.pHeadRotData = &hIvasRend->headRotData; + ctx.pSplitRendBFI = &hIvasRend->splitRendBFI; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ctx.pSplitRenderConfig = &hIvasRend->splitRenderConfig; +#endif + + return ctx; +} + + +static ivas_error getRendInputNumChannels( + const void *rendInput, + Word16 *numInChannels ) +{ + /* Using a void pointer for this function to be reusable for any input type (input_ism, input_mc, input_sba). + Assumptions: - input_base is always the first member in the input struct */ + (void) rendInput; + + *numInChannels = 2; + + return IVAS_ERR_OK; +} + +static ivas_error updateSplitPostRendPanGains( + input_split_post_rend *inputSplitPostRend, + const AUDIO_CONFIG outConfig, + ISAR_SPLIT_REND_CONFIG_DATA *hRendCfg +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + int16_t num_subframes +#endif +) +{ + ivas_error error; + rendering_context rendCtx; + LC3PLUS_CONFIG config; + Word16 iNumBlocksPerFrame, iNumLCLDIterationsPerFrame; + + (void) outConfig; + + rendCtx = inputSplitPostRend->base.ctx; + isar_renderSplitGetMultiBinPoseData_fx( hRendCfg, &inputSplitPostRend->splitPostRendWrapper.multiBinPoseData, rendCtx.pHeadRotData->sr_pose_pred_axis ); + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + config.high_res_mode_enabled = ( hRendCfg->lc3plus_highres != 0 ); +#endif + config.lc3plus_frame_duration_us = hRendCfg->codec_frame_size_ms * 1000; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + config.isar_frame_duration_us = hRendCfg->isar_frame_size_ms * 1000; +#else + IF( NE_16( num_subframes, MAX_PARAM_SPATIAL_SUBFRAMES ) ) + { + IF( hRendCfg->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS ) + { + config.ivas_frame_duration_us = ( hRendCfg->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us * num_subframes : 20000; + } + ELSE + { + config.ivas_frame_duration_us = ( hRendCfg->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ? config.lc3plus_frame_duration_us : 20000; + } + iNumLCLDIterationsPerFrame = 1; + } + ELSE + { + config.ivas_frame_duration_us = 20000; + } +#endif + + IF( GT_16( hRendCfg->codec_frame_size_ms, 0 ) ) + { + iNumLCLDIterationsPerFrame = (Word16) config.isar_frame_duration_us / ( 1000 * hRendCfg->codec_frame_size_ms ); + iNumLCLDIterationsPerFrame = max( 1, iNumLCLDIterationsPerFrame ); + iNumBlocksPerFrame = CLDFB_NO_COL_MAX * hRendCfg->codec_frame_size_ms / 20; + } + ELSE + { + iNumLCLDIterationsPerFrame = 1; + iNumBlocksPerFrame = CLDFB_NO_COL_MAX; + } + + config.channels = BINAURAL_CHANNELS; + config.samplerate = *inputSplitPostRend->base.ctx.pOutSampleRate; + + IF( hRendCfg->codec == ISAR_SPLIT_REND_CODEC_LCLD ) + { + IF( ( error = isar_splitBinLCLDDecOpen( &inputSplitPostRend->splitPostRendWrapper.hSplitBinLCLDDec, *inputSplitPostRend->base.ctx.pOutSampleRate, BINAURAL_CHANNELS, iNumBlocksPerFrame, iNumLCLDIterationsPerFrame ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE IF( hRendCfg->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS ) + { + IF( ( error = ISAR_LC3PLUS_DEC_Open( config, + &inputSplitPostRend->splitPostRendWrapper.hLc3plusDec ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + IF( ( error = isar_splitBinPostRendOpen( &inputSplitPostRend->splitPostRendWrapper.hBinHrSplitPostRend, &inputSplitPostRend->splitPostRendWrapper.multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static ivas_error setRendInputActiveSplitPostRend( + void *input, + const AUDIO_CONFIG inConfig, + const IVAS_REND_InputId id, + ISAR_SPLIT_REND_CONFIG_DATA *hRendCfg +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + const int16_t num_subframes +#endif +) +{ + ivas_error error; + rendering_context rendCtx; + AUDIO_CONFIG outConfig; + input_split_post_rend *inputSplitPostRend; + + inputSplitPostRend = (input_split_post_rend *) input; + rendCtx = inputSplitPostRend->base.ctx; + outConfig = *rendCtx.pOutConfig; + + IF( ( error = allocateInputBaseBufferData_fx( &inputSplitPostRend->bufferData_fx, MAX_CLDFB_BIN_BUFFER_LENGTH ) ) != IVAS_ERR_OK ) + { + return error; + } + + initRendInputBase_fx( &inputSplitPostRend->base, inConfig, id, rendCtx, inputSplitPostRend->bufferData_fx, MAX_CLDFB_BIN_BUFFER_LENGTH ); + + inputSplitPostRend->numCachedSamples = 0; + + if ( ( error = updateSplitPostRendPanGains( inputSplitPostRend, outConfig, hRendCfg +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + num_subframes +#endif + ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +static void clearInputSplitRend( + input_split_post_rend *inputSplitRend ) +{ + rendering_context rendCtx; + + rendCtx = inputSplitRend->base.ctx; + + freeInputBaseBufferData_fx( &inputSplitRend->bufferData_fx ); + + initRendInputBase_fx( &inputSplitRend->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); + + IF( inputSplitRend->splitPostRendWrapper.hBinHrSplitPostRend != NULL ) + { + isar_splitBinPostRendClose( &inputSplitRend->splitPostRendWrapper.hBinHrSplitPostRend ); + } + + IF( inputSplitRend->splitPostRendWrapper.hSplitBinLCLDDec != NULL ) + { + isar_splitBinLCLDDecClose( &inputSplitRend->splitPostRendWrapper.hSplitBinLCLDDec ); + } + + IF( inputSplitRend->splitPostRendWrapper.hLc3plusDec != NULL ) + { + ISAR_LC3PLUS_DEC_Close( &inputSplitRend->splitPostRendWrapper.hLc3plusDec ); + } + + return; +} + + +/*------------------------------------------------------------------------- + * ISAR_POST_REND_open() + * + * + *------------------------------------------------------------------------*/ +ivas_error ISAR_POST_REND_open( + ISAR_POST_REND_HANDLE *phIvasRend, /* i/o: Pointer to renderer handle */ + const Word32 outputSampleRate, /* i : output sampling rate */ + const AUDIO_CONFIG outConfig, /* i : output audio config */ + const bool asHrtfBinary, /* i : load hrtf binary file */ + const Word16 nonDiegeticPan, /* i : non-diegetic object flag */ + const Word32 nonDiegeticPanGain, /* i : non-diegetic panning gain */ + const Word16 num_subframes ) /* i : number of subframes */ +{ + Word16 i; + ISAR_POST_REND_HANDLE hIvasRend; + ivas_error error; + Word16 numOutChannels; + + (void) asHrtfBinary; + (void) nonDiegeticPan; + (void) nonDiegeticPanGain; + + /* Validate function arguments */ + IF( phIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( ( error = validateOutputSampleRate( outputSampleRate, outConfig ) ) != IVAS_ERR_OK ) + { + return error; + } + + *phIvasRend = (ISAR_POST_REND_HANDLE) malloc( sizeof( struct ISAR_POST_REND ) ); + IF( *phIvasRend == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + + hIvasRend = *phIvasRend; + hIvasRend->sampleRateOut = outputSampleRate; + hIvasRend->outputConfig = outConfig; + hIvasRend->hLimiter = NULL; + hIvasRend->num_subframes = 1; +#ifdef DEBUGGING + hIvasRend->numClipping = 0; +#endif + hIvasRend->num_subframes = num_subframes; + + /* Initialize limiter */ + IF( ( error = ISAR_POST_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = initLimiter( &hIvasRend->hLimiter, numOutChannels, outputSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Initialize headrotation data */ + IF( ( error = initHeadRotation( hIvasRend ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Initialize inputs */ + + FOR( i = 0; i < RENDERER_MAX_BIN_INPUTS; ++i ) + { + initRendInputBase_fx( &hIvasRend->inputsSplitPost[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 ); + + isar_init_split_post_rend_handles( &hIvasRend->inputsSplitPost[i].splitPostRendWrapper ); + + hIvasRend->splitRendBFI = 0; + hIvasRend->inputsSplitPost[i].bufferData_fx = NULL; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_NumOutChannels() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_POST_REND_NumOutChannels( + ISAR_POST_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + Word16 *numOutChannels /* o : number of output channels */ +) +{ + /* Validate function arguments */ + IF( hIvasRend == NULL || numOutChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *numOutChannels = 2; + + return IVAS_ERR_OK; +} + +static IVAS_REND_InputId makeInputId( + AUDIO_CONFIG config, + const Word32 inputIndex ) +{ + /* Put config type in second byte (from LSB), put index + 1 in first byte + * + * Index is incremented here so that a valid ID can never be 0. */ + return (IVAS_REND_InputId) ( ( ( (UWord32) isar_getAudioConfigType( config ) ) << 8 ) | ( inputIndex + 1 ) ); +} + +static ivas_error getInputById( + ISAR_POST_REND_HANDLE hIvasRend, + const IVAS_REND_InputId inputId, + void **ppInput ) +{ + Word32 inputIndex; + IVAS_REND_AudioConfigType configType; + input_base *pInputBase; + + /* Reverse makeInputId() */ + inputIndex = ( inputId & 0xFF ) - 1; + configType = ( inputId & 0xFF00 ) >> 8; + + /* Validate values derived from input ID */ + IF( inputIndex < 0 ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + SWITCH( configType ) + { + case ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL: + if ( inputIndex > RENDERER_MAX_BIN_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsSplitPost[inputIndex].base; + BREAK; + default: + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Ensure input ID matches and that input is active */ + IF( pInputBase->id != inputId || pInputBase->inConfig == IVAS_AUDIO_CONFIG_INVALID ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Validation done, set value via output parameter */ + *ppInput = pInputBase; + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_SetInputGain() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_POST_REND_SetInputGain( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + const Word32 gain /* i : linear gain (not in dB) */ +) +{ + input_base *inputBase; + ivas_error error; + + /* Validate function arguments */ + IF( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + printf( "Hoo\n" ); + return error; + } + + inputBase->gain_fx = gain; + + return IVAS_ERR_OK; +} + +static ivas_error getConstInputById( + ISAR_POST_REND_CONST_HANDLE hIvasRend, + const ISAR_POST_REND_InputId inputId, + const void **ppInput ) +{ + Word32 inputIndex; + IVAS_REND_AudioConfigType configType; + const input_base *pInputBase; + + /* Reverse makeInputId() */ + inputIndex = ( inputId & 0xFF ) - 1; + configType = ( inputId & 0xFF00 ) >> 8; + + /* Validate values derived from input ID */ + IF( inputIndex < 0 ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + SWITCH( configType ) + { + case ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL: + IF( inputIndex > RENDERER_MAX_BIN_INPUTS ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + pInputBase = &hIvasRend->inputsSplitPost[inputIndex].base; + BREAK; + default: + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Ensure input ID matches and that input is active */ + IF( pInputBase->id != inputId || pInputBase->inConfig == IVAS_AUDIO_CONFIG_INVALID ) + { + return IVAS_ERR_INVALID_INPUT_ID; + } + + /* Validation done, set value via output parameter */ + *ppInput = pInputBase; + + return IVAS_ERR_OK; +} + +static ivas_error findFreeInputSlot( + const void *inputs, + const Word32 inputStructSize, + const Word32 maxInputs, + Word32 *inputIndex ) +{ + /* Using a void pointer and a separately provided size is a hack for this function + to be reusable for arrays of any input type (input_ism, input_mc, input_sba, input_masa). + Assumptions: + - input_base is always the first member in the input struct + - provided size is correct + */ + + Word32 i; + bool canAddInput; + const UWord8 *pByte; + const input_base *pInputBase; + + canAddInput = false; + pByte = inputs; + /* Find first unused input in array */ + FOR( i = 0; i < maxInputs; ++i ) + { + pInputBase = (const input_base *) pByte; + + IF( pInputBase->inConfig == IVAS_AUDIO_CONFIG_INVALID ) + { + *inputIndex = i; + canAddInput = true; + BREAK; + } + pByte += inputStructSize; + } + + IF( !canAddInput ) + { + return IVAS_ERR_TOO_MANY_INPUTS; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_AddInput() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_AddInput( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_AUDIO_CONFIG inConfig, /* i : audio config for a new input */ + ISAR_POST_REND_InputId *inputId /* o : ID of the new input */ +) +{ + ivas_error error; + Word32 maxNumInputsOfType; + void *inputsArray; + Word32 inputStructSize; + ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, ISAR_SPLIT_REND_CONFIG_DATA * +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + int16_t +#endif + ); + Word32 inputIndex; + + /* Validate function arguments */ + IF( hIvasRend == NULL || inputId == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + SWITCH( isar_getAudioConfigType( inConfig ) ) + { + case ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL: + maxNumInputsOfType = RENDERER_MAX_BIN_INPUTS; + inputsArray = hIvasRend->inputsSplitPost; + inputStructSize = sizeof( *hIvasRend->inputsSplitPost ); + activateInput = setRendInputActiveSplitPostRend; + BREAK; + default: + return IVAS_ERR_INVALID_INPUT_FORMAT; + } + + /* Find first free input in array corresponding to input type */ + IF( ( error = findFreeInputSlot( inputsArray, inputStructSize, maxNumInputsOfType, &inputIndex ) ) != IVAS_ERR_OK ) + { + return error; + } + + *inputId = makeInputId( inConfig, inputIndex ); + if ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, &hIvasRend->splitRenderConfig +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + hIvasRend->num_subframes +#endif + ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_GetInputNumChannels() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_GetInputNumChannels( + ISAR_POST_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + Word16 *numChannels /* o : number of channels of the input */ +) +{ + ivas_error error; + const input_base *pInput; + + /* Validate function arguments */ + IF( hIvasRend == NULL || numChannels == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( ( error = getConstInputById( hIvasRend, inputId, (const void **) &pInput ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( ( error = getRendInputNumChannels( pInput, numChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_GetDelay() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_GetDelay( + ISAR_POST_REND_CONST_HANDLE hIvasRend, /* i : Renderer state */ + Word16 *nSamples, /* o : Renderer delay in samples */ + Word32 *timeScale /* o : Time scale of the delay, equal to renderer output sampling rate */ +) +{ + Word16 i; + Word32 latency_ns; + Word32 max_latency_ns; + + /* Validate function arguments */ + IF( hIvasRend == NULL || nSamples == NULL || timeScale == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *timeScale = hIvasRend->sampleRateOut; + *nSamples = 0; + max_latency_ns = 0; + + /* Compute the maximum delay across all inputs */ + FOR( i = 0; i < RENDERER_MAX_BIN_INPUTS; i++ ){ + IF( hIvasRend->inputsSplitPost[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ){ + latency_ns = 0; + IF( hIvasRend->inputsSplitPost[i].splitPostRendWrapper.hLc3plusDec != NULL ) + { + int32_t lc3plusDelaySamples; + ISAR_LC3PLUS_DEC_GetDelay( hIvasRend->inputsSplitPost[i].splitPostRendWrapper.hLc3plusDec, &lc3plusDelaySamples ); + latency_ns = (Word32) ( ( ( (Word64) lc3plusDelaySamples * 1000000000 ) + ( *timeScale / 2 ) ) / *timeScale ); + } + IF( hIvasRend->inputsSplitPost[i].splitPostRendWrapper.multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + latency_ns += IVAS_FB_DEC_DELAY_NS; + } + ELSE IF( hIvasRend->inputsSplitPost[i].splitPostRendWrapper.hSplitBinLCLDDec != NULL ) + { + latency_ns += IVAS_FB_DEC_DELAY_NS; + } + max_latency_ns = max( max_latency_ns, latency_ns ); +} +} + +*nSamples = (Word16) ( ( ( (Word64) max_latency_ns * *timeScale ) + 500000000 ) / 1000000000 ); + +return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_FeedInputAudio() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_POST_REND_FeedInputAudio( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + const ISAR_POST_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ +) +{ + ivas_error error; + input_base *inputBase; + Word16 numInputChannels; + Word16 cldfb2tdSampleFact; + + /* Validate function arguments */ + IF( hIvasRend == NULL || inputAudio.data_fx == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + cldfb2tdSampleFact = ( inputAudio.config.is_cldfb ) ? 2 : 1; + + IF( LE_16( inputAudio.config.numSamplesPerChannel, 0 ) || ( LT_16( MAX_BUFFER_LENGTH_PER_CHANNEL, inputAudio.config.numSamplesPerChannel ) && EQ_16( inputAudio.config.is_cldfb, 0 ) ) || + ( LT_16( DEPR_i_mult( MAX_BUFFER_LENGTH_PER_CHANNEL, cldfb2tdSampleFact ), inputAudio.config.numSamplesPerChannel ) && EQ_16( inputAudio.config.is_cldfb, 1 ) ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Buffer size outside of supported range" ); + } + + IF( LE_16( inputAudio.config.numChannels, 0 ) || LT_16( MAX_INPUT_CHANNELS, inputAudio.config.numChannels ) ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + IF( isar_getAudioConfigType( hIvasRend->outputConfig ) == ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && + ( inputAudio.config.numSamplesPerChannel * 1000 / cldfb2tdSampleFact ) != ( BINAURAL_RENDERING_FRAME_SIZE_MS * hIvasRend->num_subframes ) * hIvasRend->sampleRateOut ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" ); + } + + IF( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + printf( "Foo\n" ); + return error; + } + + IF( ( error = getRendInputNumChannels( inputBase, &numInputChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( numInputChannels != inputAudio.config.numChannels ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + inputBase->inputBuffer.config = inputAudio.config; + + mvl2l( inputAudio.data_fx, inputBase->inputBuffer.data_fx, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); + + inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel / cldfb2tdSampleFact; + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_InitConfig() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_POST_REND_InitConfig( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const AUDIO_CONFIG outAudioConfig /* i : output audioConfig */ +) +{ + bool rendererConfigEnabled; + + rendererConfigEnabled = ( isar_getAudioConfigType( outAudioConfig ) == ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL ); + + IF( rendererConfigEnabled ) + { + hIvasRend->rendererConfigEnabled = 1; + } + ELSE + { + hIvasRend->rendererConfigEnabled = 0; + } + + IF( rendererConfigEnabled ) + { + hIvasRend->splitRenderConfig.splitRendBitRate = SPLIT_REND_768k; + hIvasRend->splitRenderConfig.dof = 3; + hIvasRend->splitRenderConfig.hq_mode = 0; + hIvasRend->splitRenderConfig.codec_delay_ms = 0; + hIvasRend->splitRenderConfig.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hIvasRend->splitRenderConfig.isar_frame_size_ms = 0; /* 0 means "use default for selected codec" */ +#endif + hIvasRend->splitRenderConfig.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + hIvasRend->splitRenderConfig.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + hIvasRend->splitRenderConfig.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_DEFAULT; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_GetRenderConfig() + * + * + *-------------------------------------------------------------------*/ +Word16 ISAR_POST_REND_GetRenderConfig( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: IVAS decoder handle */ + const ISAR_SPLIT_REND_CONFIG_HANDLE splitRenderConfig /* o : Render configuration handle */ +) +{ + ISAR_SPLIT_REND_CONFIG_DATA hRCin; + + IF( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hRCin = hIvasRend->splitRenderConfig; + + splitRenderConfig->splitRendBitRate = SPLIT_REND_768k; + splitRenderConfig->dof = 3; + splitRenderConfig->hq_mode = 0; + splitRenderConfig->codec_delay_ms = 0; + splitRenderConfig->codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + splitRenderConfig->isar_frame_size_ms = 0; /* 0 means "use default for selected codec" */ +#endif + splitRenderConfig->codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + splitRenderConfig->poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + splitRenderConfig->rendererSelection = hRCin.rendererSelection; + + return IVAS_ERR_OK; +} +/*-------------------------------------------------------------------* + * ISAR_POST_REND_FeedSplitBinauralBitstream() + * + * + *-------------------------------------------------------------------*/ +ivas_error ISAR_POST_REND_FeedSplitBinauralBitstream( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + ISAR_POST_REND_BitstreamBuffer *hBits /* i : buffer for input bitstream */ +) +{ + ivas_error error; + input_base *inputBase; + input_split_post_rend *inputSplitPostRend; + + /* Validate function arguments */ + IF( hIvasRend == NULL || hBits == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ) != IVAS_ERR_OK ) + { + printf( "Goo\n" ); + return error; + } + + inputSplitPostRend = (input_split_post_rend *) inputBase; + inputSplitPostRend->hBits = hBits; + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_SetHeadRotation() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_SetHeadRotation( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_QUATERNION headRot, /* i : head orientations for next rendering call */ + const IVAS_VECTOR3 Pos, /* i : listener positions for next rendering call */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis, /* i : external control for rotation axis for split rendering */ + const Word16 sf_idx /* i : subframe index */ +) +{ + IVAS_QUATERNION rotQuat; + + /* Validate function arguments */ + IF( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + IF( isar_getAudioConfigType( hIvasRend->outputConfig ) != ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL ) + { + /* Head rotation can be set only with binaural output */ + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + hIvasRend->headRotData.headRotEnabled = 1; + + /* check for Euler angle signaling */ + IF( EQ_32( headRot.w_fx, -12582912 ) ) + { + Euler2Quat_fx( deg2rad_fx( headRot.x_fx ), deg2rad_fx( headRot.y_fx ), deg2rad_fx( headRot.z_fx ), &rotQuat ); + } + ELSE + { + rotQuat = headRot; + } + + hIvasRend->headRotData.headPositions[sf_idx] = rotQuat; + hIvasRend->headRotData.Pos[sf_idx] = Pos; + hIvasRend->headRotData.sr_pose_pred_axis = rot_axis; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_SetSplitRendBFI() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_SetSplitRendBFI( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const Word16 bfi /* i: BFI flag */ +) +{ + hIvasRend->splitRendBFI = bfi; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static ivas_error splitBinLc3plusDecode( + ISAR_SPLIT_POST_REND_WRAPPER *hSplitBin, + ISAR_SPLIT_REND_BITS_HANDLE bits, + Word32 outputBuffer[BINAURAL_CHANNELS][L_FRAME48k], +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + ISAR_SPLIT_REND_POSE_CORRECTION_MODE pose_correction, +#endif + const int16_t SplitRendBFI ) +{ + ivas_error error; + Word32 *channel_ptrs[MAX_HEAD_ROT_POSES * 2]; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word32 lc3plusBitstreamSize; +#else + Word32 lc3plusBitrateId, lc3plusBitstreamSize; +#endif + + push_wmops( "splitBinLc3plusDecode" ); + assert( hSplitBin->hLc3plusDec != NULL ); + + for ( Word16 i = 0; i < BINAURAL_CHANNELS * hSplitBin->multiBinPoseData.num_poses; ++i ) + { + channel_ptrs[i] = outputBuffer[i]; + } + + if ( SplitRendBFI == 0 ) + { + /* Find next byte boundary */ + while ( bits->bits_read % 8 != 0 ) + { + ++bits->bits_read; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* Size is in bytes */ + assert( ( bits->bits_written - bits->bits_read ) % 8 == 0 ); + lc3plusBitstreamSize = ( bits->bits_written - bits->bits_read ) / 8; +#else + /* Read LC3plus bitstream size info */ + lc3plusBitrateId = ISAR_SPLIT_REND_BITStream_read_int32( bits, 8 ); + lc3plusBitstreamSize = isar_get_lc3plus_size_from_id( (Word8) lc3plusBitrateId, pose_correction, (Word16) ( hSplitBin->hLc3plusDec->config.ivas_frame_duration_us / 1000 ) ); +#endif + + if ( ( error = ISAR_LC3PLUS_DEC_Decode( hSplitBin->hLc3plusDec, &bits->bits_buf[bits->bits_read / 8], lc3plusBitstreamSize, channel_ptrs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ISAR_LC3PLUS_DEC_Conceal( hSplitBin->hLc3plusDec, channel_ptrs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + pop_wmops(); + return IVAS_ERR_OK; +} + +static ivas_error renderSplitBinauralWithPostRot( + input_split_post_rend *splitBinInput, + IVAS_REND_AudioBuffer outAudio, + const Word16 SplitRendBFI, + const Word16 num_subframes ) +{ + Word32 Cldfb_RealBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural_fx[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + ivas_error error; + Word32 Cldfb_RealBuffer_Binaural_5ms_fx[MAX_PARAM_SPATIAL_SUBFRAMES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word32 Cldfb_ImagBuffer_Binaural_5ms_fx[MAX_PARAM_SPATIAL_SUBFRAMES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX] = { 0 }; + + IVAS_QUATERNION QuaternionsPost[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t sf_idx, ch_idx; + ISAR_SPLIT_REND_BITS_DATA bits; + Word32 tmpCrendBuffer_fx[BINAURAL_CHANNELS][L_FRAME48k] = { 0 }; + Word32 tmpCrendBuffer_sf_fx[BINAURAL_CHANNELS][L_FRAME48k] = { 0 }; + + ISAR_SPLIT_POST_REND_WRAPPER *hSplitBin; + Word8 isPostRendInputCldfb; + Word16 chnlIdx, slotIdx, smplIdx; + Word16 preRendFrameSize_ms; + Word16 outBufNumSamplesPerChannel, outBufNumColPerChannel; + Word16 numSamplesPerChannelCacheSize, numColPerChannelCacheSize; + + Word32 *readPtr_fx, *writePtr_fx; + Word16 Q_cldfb_final[MAX_PARAM_SPATIAL_SUBFRAMES] = { 0 }; + Word16 Q_out[MAX_PARAM_SPATIAL_SUBFRAMES][BINAURAL_CHANNELS] = { 0 }; + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + uint32_t ivas_frame_duration_us; +#endif + Word16 iNumBlocksPerFrame, iNumLCLDIterationsPerFrame; + const ISAR_POST_REND_HeadRotData *pHeadRotData; + + isPostRendInputCldfb = 0; + push_wmops( "renderSplitBinauralWithPostRot" ); + error = IVAS_ERR_OK; + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + if ( outAudio.config.numSamplesPerChannel / *splitBinInput->base.ctx.pOutSampleRate > splitBinInput->hBits->config.isar_frame_size_ms ) + { + return IVAS_ERR_INTERNAL_FATAL; + } +#endif + + pHeadRotData = splitBinInput->base.ctx.pHeadRotData; + hSplitBin = &splitBinInput->splitPostRendWrapper; + convertBitsBufferToInternalBitsBuff( *splitBinInput->hBits, &bits ); + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + ivas_frame_duration_us = 20000; + if ( splitBinInput->splitPostRendWrapper.hLc3plusDec != NULL ) + { + ivas_frame_duration_us = splitBinInput->splitPostRendWrapper.hLc3plusDec->config.isar_frame_duration_us; + } +#endif + + iNumLCLDIterationsPerFrame = 1; + iNumBlocksPerFrame = CLDFB_NO_COL_MAX; + IF( splitBinInput->splitPostRendWrapper.hSplitBinLCLDDec != NULL ) + { + iNumBlocksPerFrame = splitBinInput->splitPostRendWrapper.hSplitBinLCLDDec->iNumBlocks; + iNumLCLDIterationsPerFrame = splitBinInput->splitPostRendWrapper.hSplitBinLCLDDec->iNumIterations; + } + + outBufNumSamplesPerChannel = outAudio.config.numSamplesPerChannel / num_subframes; + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + QuaternionsPost[sf_idx] = pHeadRotData->headPositions[sf_idx]; + } + + IF( !SplitRendBFI ) + { + hSplitBin->first_good_frame_received = 1; + } + + IF( EQ_16( hSplitBin->first_good_frame_received, 1 ) ) + { + IF( bits.pose_correction == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + IF( !SplitRendBFI ) + { +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + isar_splitBinPostRendMdDec_fx( &bits, hSplitBin->hBinHrSplitPostRend, &hSplitBin->multiBinPoseData, hSplitBin->hBinHrSplitPreRend ); +#else + isar_splitBinPostRendMdDec_fx( &bits, hSplitBin->hBinHrSplitPostRend, &hSplitBin->multiBinPoseData ); +#endif + } + } + + /*copy pose correction after MD is parsed*/ + hSplitBin->multiBinPoseData.poseCorrectionMode = bits.pose_correction; + + /* decode audio */ + IF( splitBinInput->base.inConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + IF( bits.codec == ISAR_SPLIT_REND_CODEC_LCLD ) + { + isPostRendInputCldfb = 1; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * bits.isar_frame_size_ms / 1000 ) - outBufNumSamplesPerChannel; +#else + preRendFrameSize_ms = (int16_t) ( ivas_frame_duration_us ) / 1000; + + numSamplesPerChannelCacheSize = (int16_t) ( *splitBinInput->base.ctx.pOutSampleRate * ( preRendFrameSize_ms - bits.codec_frame_size_ms ) / 1000 ); +#endif + + outBufNumColPerChannel = MAX_PARAM_SPATIAL_SUBFRAMES; + numColPerChannelCacheSize = sub( DEPR_i_mult( iNumBlocksPerFrame, iNumLCLDIterationsPerFrame ), outBufNumColPerChannel ); + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + IF( splitBinInput->numCachedSamples == 0 ) + { + IF( bits.codec == ISAR_SPLIT_REND_CODEC_LCLD ) + { + isar_splitBinLCLDDecProcess( hSplitBin->hSplitBinLCLDDec, &bits, Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, &Q_cldfb_final[sf_idx], SplitRendBFI ); // Q_cldfb_final + + /* copy data over to 5ms buffer */ + FOR( chnlIdx = 0; chnlIdx < BINAURAL_CHANNELS; ++chnlIdx ) + { + FOR( slotIdx = 0; slotIdx < 4 /*CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES*/; ++slotIdx ) + { + mvl2l( Cldfb_RealBuffer_Binaural_fx[chnlIdx][slotIdx], Cldfb_RealBuffer_Binaural_5ms_fx[sf_idx][chnlIdx][slotIdx], CLDFB_NO_CHANNELS_MAX ); + mvl2l( Cldfb_ImagBuffer_Binaural_fx[chnlIdx][slotIdx], Cldfb_ImagBuffer_Binaural_5ms_fx[sf_idx][chnlIdx][slotIdx], CLDFB_NO_CHANNELS_MAX ); + } + } + + /* cache the remaining 15ms */ + splitBinInput->numCachedSamples = numColPerChannelCacheSize; + writePtr_fx = splitBinInput->bufferData_fx; + FOR( slotIdx = 4 /*CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES*/; slotIdx < DEPR_i_mult( iNumBlocksPerFrame, iNumLCLDIterationsPerFrame ); ++slotIdx ) + { + FOR( chnlIdx = 0; chnlIdx < BINAURAL_CHANNELS; ++chnlIdx ) + { + FOR( smplIdx = 0; smplIdx < CLDFB_NO_CHANNELS_MAX; ++smplIdx ) + { + *writePtr_fx++ = Cldfb_RealBuffer_Binaural_fx[chnlIdx][slotIdx][smplIdx]; + } + FOR( smplIdx = 0; smplIdx < CLDFB_NO_CHANNELS_MAX; ++smplIdx ) + { + *writePtr_fx++ = Cldfb_ImagBuffer_Binaural_fx[chnlIdx][slotIdx][smplIdx]; + } + } + } + } + ELSE + { + Q_out[sf_idx][0] = 0; + Q_out[sf_idx][1] = 0; + if ( ( error = splitBinLc3plusDecode( hSplitBin, &bits, tmpCrendBuffer_fx, +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + bits.pose_correction, +#endif + SplitRendBFI ) ) != IVAS_ERR_OK ) // Q0 + { + return error; + } + + /* cache the remaining 15ms */ + splitBinInput->numCachedSamples = numSamplesPerChannelCacheSize; + mvl2l( &tmpCrendBuffer_fx[0][outBufNumSamplesPerChannel], splitBinInput->bufferData_fx, numSamplesPerChannelCacheSize ); + mvl2l( &tmpCrendBuffer_fx[1][outBufNumSamplesPerChannel], splitBinInput->bufferData_fx + numSamplesPerChannelCacheSize, numSamplesPerChannelCacheSize ); + } + } + ELSE + { + /* copy from cache */ + IF( bits.codec == ISAR_SPLIT_REND_CODEC_LCLD ) + { + Word16 readOffset = sub( numColPerChannelCacheSize, splitBinInput->numCachedSamples ); + readPtr_fx = splitBinInput->bufferData_fx; + Q_cldfb_final[sf_idx] = Q_cldfb_final[sf_idx - 1]; + isPostRendInputCldfb = 1; + + readPtr_fx += 2 * readOffset * CLDFB_NO_CHANNELS_MAX * BINAURAL_CHANNELS; + FOR( slotIdx = 0; slotIdx < 4 /*CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES*/; ++slotIdx ) + { + FOR( chnlIdx = 0; chnlIdx < BINAURAL_CHANNELS; ++chnlIdx ) + { + FOR( smplIdx = 0; smplIdx < CLDFB_NO_CHANNELS_MAX; ++smplIdx ) + { + Cldfb_RealBuffer_Binaural_5ms_fx[sf_idx][chnlIdx][slotIdx][smplIdx] = *readPtr_fx++; + } + FOR( smplIdx = 0; smplIdx < CLDFB_NO_CHANNELS_MAX; ++smplIdx ) + { + Cldfb_ImagBuffer_Binaural_5ms_fx[sf_idx][chnlIdx][slotIdx][smplIdx] = *readPtr_fx++; + } + } + } + + splitBinInput->numCachedSamples -= outBufNumColPerChannel; + } + ELSE + { + Word16 readOffset = numSamplesPerChannelCacheSize - splitBinInput->numCachedSamples; + mvl2l( splitBinInput->bufferData_fx + readOffset, &tmpCrendBuffer_fx[0][sf_idx * outBufNumSamplesPerChannel], outBufNumSamplesPerChannel ); + mvl2l( splitBinInput->bufferData_fx + readOffset + numSamplesPerChannelCacheSize, &tmpCrendBuffer_fx[1][sf_idx * outBufNumSamplesPerChannel], outBufNumSamplesPerChannel ); + Q_out[sf_idx][0] = Q_out[sf_idx - 1][0]; + Q_out[sf_idx][1] = Q_out[sf_idx - 1][1]; + splitBinInput->numCachedSamples -= outBufNumSamplesPerChannel; + } + } + } + } + ELSE + { + copyBufferTo2dArray_fx( splitBinInput->base.inputBuffer, tmpCrendBuffer_fx ); + IF( splitBinInput->numCachedSamples == 0 ) + { +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + preRendFrameSize_ms = splitBinInput->base.ctx.pSplitRenderConfig->isar_frame_size_ms; +#else + preRendFrameSize_ms = (int16_t) ( ivas_frame_duration_us ) / 1000; +#endif + numSamplesPerChannelCacheSize = (Word16) ( *splitBinInput->base.ctx.pOutSampleRate * preRendFrameSize_ms / 1000 ); + numSamplesPerChannelCacheSize -= outAudio.config.numSamplesPerChannel; + splitBinInput->numCachedSamples = numSamplesPerChannelCacheSize; + } + ELSE + { + splitBinInput->numCachedSamples -= outAudio.config.numSamplesPerChannel; + } + } + + /* apply pose correction if enabled */ + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + IF( bits.pose_correction == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE && isPostRendInputCldfb ) + { + /* 0DOF with LCLD codec requires CLDFB synthesis */ + Word16 slot_idx; + + FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + Word32 *RealBuffer_fx[CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES]; + Word32 *ImagBuffer_fx[CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 scaleFactor = 31, Q_cldfb; + + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + RealBuffer_fx[slot_idx] = Cldfb_RealBuffer_Binaural_5ms_fx[sf_idx][ch_idx][slot_idx]; + ImagBuffer_fx[slot_idx] = Cldfb_ImagBuffer_Binaural_5ms_fx[sf_idx][ch_idx][slot_idx]; + + scaleFactor = s_min( scaleFactor, s_min( getScaleFactor32( RealBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX ), getScaleFactor32( ImagBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX ) ) ); + } + scaleFactor = sub( scaleFactor, 3 ); // guarded bits + + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + Scale_sig32( RealBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX, scaleFactor ); + Scale_sig32( ImagBuffer_fx[slot_idx], CLDFB_NO_CHANNELS_MAX, scaleFactor ); + } + Q_cldfb = scaleFactor + Q_cldfb_final[sf_idx]; + Scale_sig32( hSplitBin->hBinHrSplitPostRend->cldfbSyn[ch_idx]->cldfb_state_fx, hSplitBin->hBinHrSplitPostRend->cldfbSyn[ch_idx]->p_filter_length, sub( sub( Q_cldfb, 1 ), Q11 ) ); + cldfbSynthesis_ivas_fx( RealBuffer_fx, + ImagBuffer_fx, + &( tmpCrendBuffer_fx[ch_idx][sf_idx * outBufNumSamplesPerChannel] ), + hSplitBin->hBinHrSplitPostRend->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, + hSplitBin->hBinHrSplitPostRend->cldfbSyn[ch_idx] ); // Q_cldfb - 1 + Scale_sig32( hSplitBin->hBinHrSplitPostRend->cldfbSyn[ch_idx]->cldfb_state_fx, hSplitBin->hBinHrSplitPostRend->cldfbSyn[ch_idx]->p_filter_length, sub( Q11, sub( Q_cldfb, 1 ) ) ); + Q_out[sf_idx][ch_idx] = sub( Q_cldfb, 1 ); + } + } + ELSE IF( bits.pose_correction == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + mvl2l( &tmpCrendBuffer_fx[0][sf_idx * outBufNumSamplesPerChannel], tmpCrendBuffer_sf_fx[0], outBufNumSamplesPerChannel ); + mvl2l( &tmpCrendBuffer_fx[1][sf_idx * outBufNumSamplesPerChannel], tmpCrendBuffer_sf_fx[1], outBufNumSamplesPerChannel ); + + isar_rend_CldfbSplitPostRendProcess( hSplitBin->hBinHrSplitPostRend, &hSplitBin->multiBinPoseData, QuaternionsPost[sf_idx], Cldfb_RealBuffer_Binaural_5ms_fx[sf_idx], Cldfb_ImagBuffer_Binaural_5ms_fx[sf_idx], Q_cldfb_final[sf_idx], tmpCrendBuffer_sf_fx, Q_out[sf_idx], isPostRendInputCldfb ); // Q_out[2] + + mvl2l( tmpCrendBuffer_sf_fx[0], &tmpCrendBuffer_fx[0][sf_idx * outBufNumSamplesPerChannel], outBufNumSamplesPerChannel ); + mvl2l( tmpCrendBuffer_sf_fx[1], &tmpCrendBuffer_fx[1][sf_idx * outBufNumSamplesPerChannel], outBufNumSamplesPerChannel ); + } + } + } + ELSE + { + IF( splitBinInput->base.inConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + set_l( tmpCrendBuffer_fx[ch_idx], 0, outAudio.config.numSamplesPerChannel ); + } + } + ELSE + { + copyBufferTo2dArray_fx( splitBinInput->base.inputBuffer, tmpCrendBuffer_fx ); + } + } + + convertInternalBitsBuffToBitsBuffer( splitBinInput->hBits, bits ); + + Word16 Q_max = 0, Q_temp; + FOR( Word16 i = 0; i < num_subframes; i++ ) + { + maximum_s( Q_out[i], BINAURAL_CHANNELS, &Q_temp ); + Q_max = s_max( Q_max, Q_temp ); + } + Q_max = s_min( Q_max, Q13 ); + accumulate2dArrayToBuffer_fx( tmpCrendBuffer_fx, Q_out, Q_max, &outAudio, num_subframes, outBufNumSamplesPerChannel ); + *outAudio.q_data_fx = Q_max; + + pop_wmops(); + return error; +} + +static ivas_error renderInputSplitBin( + input_split_post_rend *splitBinInput, + const AUDIO_CONFIG outConfig, + IVAS_REND_AudioBuffer outAudio, + const Word16 SplitRendBFI, + const Word16 num_subframes ) +{ + ivas_error error; + IVAS_REND_AudioBuffer inAudio; + + inAudio = splitBinInput->base.inputBuffer; + + splitBinInput->base.numNewSamplesPerChannel = 0; + + /* Apply input gain to new audio */ + v_multc_fixed( inAudio.data_fx, + splitBinInput->base.gain_fx, + inAudio.data_fx, + inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); + + SWITCH( outConfig ) + { + case IVAS_AUDIO_CONFIG_BINAURAL: + error = renderSplitBinauralWithPostRot( splitBinInput, outAudio, SplitRendBFI, num_subframes ); + BREAK; + default: + return IVAS_ERR_INVALID_OUTPUT_FORMAT; + } + + return error; +} + +static ivas_error renderActiveInputsSplitBin( + ISAR_POST_REND_HANDLE hIvasRend, + IVAS_REND_AudioBuffer outAudio ) +{ + int16_t i; + input_split_post_rend *pCurrentInput; + ivas_error error; + pCurrentInput = hIvasRend->inputsSplitPost; + FOR( i = 0; i < RENDERER_MAX_BIN_INPUTS; ++i ) + { + IF( pCurrentInput->base.inConfig == IVAS_AUDIO_CONFIG_INVALID ) + { + /* Skip inactive inputs */ + ++pCurrentInput; + continue; + } + + IF( ( error = renderInputSplitBin( pCurrentInput, hIvasRend->outputConfig, outAudio, hIvasRend->splitRendBFI, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } + ++pCurrentInput; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_getSamples() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_getSamples( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ +) +{ + ivas_error error; + Word16 numOutChannels; + Word16 cldfb2tdSampleFact; + + /* Validate function arguments */ + IF( hIvasRend == NULL || outAudio.data_fx == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + cldfb2tdSampleFact = ( outAudio.config.is_cldfb ) ? 2 : 1; + + IF( outAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 0 ) || + ( ( MAX_BUFFER_LENGTH_PER_CHANNEL * cldfb2tdSampleFact ) < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 1 ) ) + { + return IVAS_ERR_INVALID_BUFFER_SIZE; + } + + IF( LT_16( outAudio.config.numChannels, 0 ) || LT_16( MAX_OUTPUT_CHANNELS, outAudio.config.numChannels ) ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + IF( isar_getAudioConfigType( hIvasRend->outputConfig ) == ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL && + ( outAudio.config.numSamplesPerChannel * 1000 / cldfb2tdSampleFact ) != ( hIvasRend->num_subframes * BINAURAL_RENDERING_FRAME_SIZE_MS ) * hIvasRend->sampleRateOut ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" ); + } + + IF( ( error = ISAR_POST_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( numOutChannels != outAudio.config.numChannels && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + /* Clear original output buffer */ + set_l( outAudio.data_fx, 0, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); + + IF( ( error = renderActiveInputsSplitBin( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + +#ifndef DISABLE_LIMITER +#ifdef DEBUGGING + hIvasRend->numClipping += +#endif + Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.q_data_fx ); + limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.q_data_fx ); +#endif + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_GetSplitBinauralSamples() + * + * + *-------------------------------------------------------------------*/ + +ivas_error ISAR_POST_REND_GetSplitBinauralSamples( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio, /* i/o: buffer for output audio */ + bool *needNewFrame ) +{ + ivas_error error; + + IF( ( error = ISAR_POST_REND_getSamples( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + *needNewFrame = hIvasRend->inputsSplitPost[0].numCachedSamples == 0; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ISAR_POST_REND_Close() + * + * + *-------------------------------------------------------------------*/ +void ISAR_POST_REND_Close( + ISAR_POST_REND_HANDLE *phIvasRend /* i/o: Pointer to renderer handle */ +) +{ + UWord16 i; + ISAR_POST_REND_HANDLE hIvasRend; + + /* Validate function arguments */ + IF( phIvasRend == NULL || *phIvasRend == NULL ) + { + return; + } + hIvasRend = *phIvasRend; + + FOR( i = 0; i < RENDERER_MAX_BIN_INPUTS; ++i ) + { + clearInputSplitRend( &hIvasRend->inputsSplitPost[i] ); + } + + ivas_limiter_close_splitRend( &hIvasRend->hLimiter ); + + free( hIvasRend ); + *phIvasRend = NULL; + + return; +} + + +ivas_error ISAR_REND_SetSplitRendBitstreamHeader( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + const ISAR_SPLIT_REND_CODEC codec, /* o: codec setting */ + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection, /* o: pose correction mode */ + const int16_t codec_frame_size_ms /* i: codec frame size setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + const int16_t isar_frame_size_ms, /* i: isar codec frame size setting */ + const int16_t lc3plus_highres /* i: LC3plus Hig-Res setting. Ignored if codec is not LC3plus */ +#endif +) +{ + IF( hIvasRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + hIvasRend->splitRenderConfig.codec = codec; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hIvasRend->splitRenderConfig.isar_frame_size_ms = isar_frame_size_ms; +#endif + hIvasRend->splitRenderConfig.codec_frame_size_ms = codec_frame_size_ms; + hIvasRend->splitRenderConfig.poseCorrectionMode = poseCorrection; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hIvasRend->splitRenderConfig.lc3plus_highres = lc3plus_highres; +#endif + return IVAS_ERR_OK; +} + +#ifdef DEBUGGING +/*-------------------------------------------------------------------* + * ISAR_POST_REND_GetNoCLipping() + * + * + *-------------------------------------------------------------------*/ + +int32_t ISAR_POST_REND_GetNoCLipping( + ISAR_POST_REND_HANDLE hIvasRend ) +{ + return hIvasRend->numClipping; +} + +int32_t ISAR_POST_REND_GetCntFramesLimited( + ISAR_POST_REND_CONST_HANDLE hIvasRend ) +{ + if ( hIvasRend->hLimiter == NULL ) + { + return 0; + } + + return hIvasRend->hLimiter->cnt_frames_limited; +} +#endif + + +#endif diff --git a/lib_isar/lib_isar_post_rend.h b/lib_isar/lib_isar_post_rend.h new file mode 100644 index 000000000..cc32086fa --- /dev/null +++ b/lib_isar/lib_isar_post_rend.h @@ -0,0 +1,225 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef LIB_ISAR_POST_REND_H +#define LIB_ISAR_POST_REND_H + +#include "common_api_types.h" +#include + +#ifndef SPLIT_REND_WITH_HEAD_ROT + +int32_t ISAR_POST_REND_void_func( void ); + +#else + +/*---------------------------------------------------------------------* + * Renderer constants + *---------------------------------------------------------------------*/ + +#define RENDERER_MAX_ISAR_MD_INPUTS 1 +#define RENDERER_MAX_BIN_INPUTS 1 + +/*---------------------------------------------------------------------* + * Renderer structures + *---------------------------------------------------------------------*/ + +typedef struct +{ + int32_t bufLenInBytes; + int32_t bitsWritten; + int32_t bitsRead; + ISAR_SPLIT_REND_CODEC codec; + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection; + int16_t codec_frame_size_ms; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int16_t isar_frame_size_ms; + int16_t lc3plusHighRes; +#endif +} ISAR_POST_REND_BitstreamBufferConfig; + +typedef struct +{ + ISAR_POST_REND_BitstreamBufferConfig config; + uint8_t *bits; +} ISAR_POST_REND_BitstreamBuffer; + +typedef enum +{ + ISAR_POST_REND_AUDIO_CONFIG_TYPE_BINAURAL = 0, + ISAR_POST_REND_AUDIO_CONFIG_TYPE_UNKNOWN, +} ISAR_POST_REND_AudioConfigType; + +typedef struct +{ + IVAS_REND_AudioBufferConfig config; + const Word32 *data_fx; +} ISAR_POST_REND_ReadOnlyAudioBuffer; + +typedef struct ISAR_POST_REND *ISAR_POST_REND_HANDLE; +typedef struct ISAR_POST_REND const *ISAR_POST_REND_CONST_HANDLE; + +typedef uint16_t ISAR_POST_REND_InputId; + +typedef enum _ISAR_POST_REND_COMPLEXITY_LEVEL +{ + ISAR_POST_REND_COMPLEXITY_LEVEL_ONE = 1, + ISAR_POST_REND_COMPLEXITY_LEVEL_TWO = 2, + ISAR_POST_REND_COMPLEXITY_LEVEL_THREE = 3 +} ISAR_POST_REND_COMPLEXITY_LEVEL; + + +/* clang-format off */ +/*----------------------------------------------------------------------------------* + * Renderer function prototypes + *----------------------------------------------------------------------------------*/ + +/* Functions to be called before rendering */ +ivas_error ISAR_POST_REND_open( + ISAR_POST_REND_HANDLE *phIvasRend, /* i/o: Pointer to renderer handle */ + const Word32 outputSampleRate, /* i : output sampling rate */ + const IVAS_AUDIO_CONFIG outConfig, /* i : output audio config */ + const bool asHrtfBinary, /* i : load hrtf binary file */ + const Word16 nonDiegeticPan, /* i : non-diegetic object flag */ + const Word32 nonDiegeticPanGain, /* i : non-diegetic panning gain */ + const Word16 num_subframes /* i : number of subframes */ +); + +/* Functions to be called before/during rendering */ +ivas_error ISAR_POST_REND_NumOutChannels( + ISAR_POST_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + Word16 *numOutChannels /* o : number of output channels */ +); + +ivas_error ISAR_POST_REND_AddInput( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_AUDIO_CONFIG inConfig, /* i : audio config for a new input */ + ISAR_POST_REND_InputId *inputId /* o : ID of the new input */ +); + +ivas_error ISAR_POST_REND_SetInputGain( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + const Word32 gain /* i : linear gain (not in dB) */ +); + +ivas_error ISAR_POST_REND_GetInputNumChannels( + ISAR_POST_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + Word16 *numChannels /* o : number of channels of the input */ +); +ivas_error ISAR_POST_REND_GetDelay( + ISAR_POST_REND_CONST_HANDLE hIvasRend, /* i : Renderer state */ + Word16 *nSamples, /* o : Renderer delay in samples */ + Word32 *timeScale /* o : Time scale of the delay, equal to renderer output sampling rate */ +); + +/* Functions to be called during rendering */ + +ivas_error ISAR_POST_REND_FeedInputAudio( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + const ISAR_POST_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ +); + +ivas_error ISAR_POST_REND_InitConfig( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_AUDIO_CONFIG outAudioConfig /* i : output audioConfig */ +); +Word16 ISAR_POST_REND_GetRenderConfig( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: IVAS decoder handle */ + const ISAR_SPLIT_REND_CONFIG_HANDLE splitRenderConfig /* o : Render configuration handle */ +); +ivas_error ISAR_POST_REND_FeedSplitBinauralBitstream( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const ISAR_POST_REND_InputId inputId, /* i : ID of the input */ + ISAR_POST_REND_BitstreamBuffer *hBits /* i : buffer for input bitstream */ +); + +ivas_error ISAR_POST_REND_GetSplitBinauralSamples( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio, /* i/o: buffer for output audio */ + bool* needNewFrame +); + +ivas_error ISAR_POST_REND_SetHeadRotation( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_QUATERNION headRot, /* i : head orientations for next rendering call */ + const IVAS_VECTOR3 Pos, /* i : listener positions for next rendering call */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis, /* i : external control for rotation axis for split rendering */ + const Word16 sf_idx /* i : subframe index */ +); + +ivas_error ISAR_POST_REND_SetSplitRendBFI( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const Word16 bfi /* i: BFI flag */ +); + +ivas_error ISAR_POST_REND_getSamples( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ +); + +/* Functions to be called after rendering */ + +void ISAR_POST_REND_Close( + ISAR_POST_REND_HANDLE* phIvasRend /* i/o: Pointer to renderer handle */ +); + +ivas_error ISAR_REND_SetSplitRendBitstreamHeader( + ISAR_POST_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + const ISAR_SPLIT_REND_CODEC codec, /* o: codec setting */ + const ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection, /* o: pose correction mode */ + const int16_t codec_frame_size_ms /* i: codec frame size setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + const int16_t isar_frame_size_ms, /* i: isar frame size setting */ + const int16_t lc3plus_highres /* i: LC3plus Hig-Res setting. Ignored if codec is not LC3plus */ +#endif +); + + +#ifdef DEBUGGING +int32_t ISAR_POST_REND_GetNoCLipping( + ISAR_POST_REND_HANDLE hIvasRend /* i : Renderer handle */ +); + +int32_t ISAR_POST_REND_GetCntFramesLimited( + ISAR_POST_REND_CONST_HANDLE hIvasRend /* i : Renderer handle */ +); +#endif + +#endif /* SPLIT_REND_WITH_HEAD_ROT */ + +/* clang-format on */ + +#endif /* LIB_ISAR_POST_REND_H */ diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c new file mode 100644 index 000000000..2149d2225 --- /dev/null +++ b/lib_isar/lib_isar_pre_rend.c @@ -0,0 +1,626 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + + +#include +#include "options.h" +#include +#include "ivas_prot.h" +#include "prot.h" +#include "isar_cnst.h" +#include "isar_rom_post_rend.h" +#include "lib_isar_pre_rend.h" +#include "isar_prot.h" +#ifdef DEBUGGING +#include "debug.h" +#endif +#include "wmc_auto.h" + + +#ifndef SPLIT_REND_WITH_HEAD_ROT +int32_t ISAR_PRE_REND_void_func( void ) +{ + return 0; +} + +#else + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * Local types + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------- + * Function ISAR_PRE_REND_open() + * + * + *------------------------------------------------------------------------*/ + +ivas_error ISAR_PRE_REND_open( + SPLIT_REND_WRAPPER *hSplitRendWrapper, + ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, + const Word32 OutSampleRate, + const Word16 cldfb_in_flag, + const Word16 pcm_out_flag, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const IVAS_RENDER_FRAMESIZE ivas_frame_size, /* i: IVAS frame size */ +#else + const int16_t num_subframes, /* i: number of subframes */ +#endif + const int16_t mixed_td_cldfb_flag ) +{ + ivas_error error, ch, num_ch; + UWord8 isCldfbNeeded = 0; + Word16 cldfb_in_flag_local = cldfb_in_flag; + + if ( ( error = isar_split_rend_choose_default_codec( &( pSplitRendConfig->codec ), +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + &pSplitRendConfig->isar_frame_size_ms, +#endif + &pSplitRendConfig->codec_frame_size_ms, + cldfb_in_flag_local, + pcm_out_flag, (int16_t) +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ivas_frame_size +#else + num_subframes +#endif + ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( mixed_td_cldfb_flag ) + { + cldfb_in_flag_local = 0; + } + + IF( ( error = isar_split_rend_validate_config( pSplitRendConfig, pcm_out_flag ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( EQ_16( cldfb_in_flag_local, 0 ) ) + { + isCldfbNeeded = 1; + } + ELSE IF( EQ_16( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) && cldfb_in_flag_local ) + { + isCldfbNeeded = 1; + } + ELSE IF( pcm_out_flag && cldfb_in_flag_local ) + { + isCldfbNeeded = 1; + } + + hSplitRendWrapper->hCldfbHandles = NULL; + + IF( isCldfbNeeded ) + { + IF( ( hSplitRendWrapper->hCldfbHandles = (CLDFB_HANDLES_WRAPPER_HANDLE) malloc( sizeof( CLDFB_HANDLES_WRAPPER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CLDFB handles\n" ) ); + } + num_ch = MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; + FOR( ch = 0; ch < num_ch; ch++ ) + { + hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] = NULL; + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] = NULL; + } + + num_ch = hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; + + FOR( ch = 0; ch < num_ch; ch++ ) + { + if ( ( error = openCldfb( &( hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] ), + CLDFB_ANALYSIS, + OutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + IF( ( error = openCldfb( &( hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] ), CLDFB_SYNTHESIS, OutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + IF( EQ_16( pSplitRendConfig->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + { + if ( ( error = isar_splitBinPreRendOpen( &hSplitRendWrapper->hBinHrSplitPreRend, &hSplitRendWrapper->multiBinPoseData +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + , + OutSampleRate +#endif + ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + IF( EQ_16( pcm_out_flag, 0 ) ) + { + IF( EQ_16( pSplitRendConfig->codec, ISAR_SPLIT_REND_CODEC_LC3PLUS ) ) + { + if ( ( error = split_renderer_open_lc3plus( hSplitRendWrapper, pSplitRendConfig, OutSampleRate, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ivas_frame_size +#else + num_subframes +#endif + ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + Word16 iNumBlocksPerFrame; + iNumBlocksPerFrame = ( CLDFB_NO_COL_MAX * pSplitRendConfig->codec_frame_size_ms ) / 20; + + IF( ( error = isar_splitBinLCLDEncOpen( &hSplitRendWrapper->hSplitBinLCLDEnc, OutSampleRate, BINAURAL_CHANNELS, isar_get_lcld_bitrate( pSplitRendConfig->splitRendBitRate, hSplitRendWrapper->multiBinPoseData.poseCorrectionMode ), iNumBlocksPerFrame, 1 ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + return IVAS_ERR_OK; +} + +/*------------------------------------------------------------------------- + * Function ISAR_PRE_REND_close() + * + * + *------------------------------------------------------------------------*/ +void ISAR_PRE_REND_close( + SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renerer handle */ + IVAS_REND_AudioBuffer *pSplitRendEncBuffer /* i/o: Split renderer data buffer */ +) +{ + Word16 i; + + IF( hSplitBinRend->hBinHrSplitPreRend != NULL ) + { + isar_splitBinPreRendClose( &hSplitBinRend->hBinHrSplitPreRend ); + } + + IF( hSplitBinRend->hSplitBinLCLDEnc != NULL ) + { + isar_splitBinLCLDEncClose( &hSplitBinRend->hSplitBinLCLDEnc ); + } + + IF( hSplitBinRend->hCldfbHandles != NULL ) + { + Word16 num_ch, ch; + num_ch = MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; + FOR( ch = 0; ch < num_ch; ch++ ) + { + IF( hSplitBinRend->hCldfbHandles->cldfbAna[ch] != NULL ) + { + deleteCldfb( &hSplitBinRend->hCldfbHandles->cldfbAna[ch] ); + hSplitBinRend->hCldfbHandles->cldfbAna[ch] = NULL; + } + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + IF( hSplitBinRend->hCldfbHandles->cldfbSyn[ch] != NULL ) + { + deleteCldfb( &hSplitBinRend->hCldfbHandles->cldfbSyn[ch] ); + hSplitBinRend->hCldfbHandles->cldfbSyn[ch] = NULL; + } + } +#endif + + free( hSplitBinRend->hCldfbHandles ); + hSplitBinRend->hCldfbHandles = NULL; + } + + IF( hSplitBinRend->hLc3plusEnc != NULL ) + { + ISAR_LC3PLUS_ENC_Close( &hSplitBinRend->hLc3plusEnc ); + } + + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) + { + IF( hSplitBinRend->lc3plusDelayBuffers[i] != NULL ) + { + free( hSplitBinRend->lc3plusDelayBuffers[i] ); + hSplitBinRend->lc3plusDelayBuffers[i] = NULL; + } + if ( hSplitBinRend->lc3plusDelayBuffers_fx[i] != NULL ) + { + free( hSplitBinRend->lc3plusDelayBuffers_fx[i] ); + hSplitBinRend->lc3plusDelayBuffers_fx[i] = NULL; + } + } + + IF( pSplitRendEncBuffer != NULL ) + { + + IF( pSplitRendEncBuffer->data != NULL ) + { + free( pSplitRendEncBuffer->data ); + pSplitRendEncBuffer->data = NULL; + } + + pSplitRendEncBuffer->config.numChannels = 0; + pSplitRendEncBuffer->config.numSamplesPerChannel = 0; + } + + return; +} + + +/*-------------------------------------------------------------------------* + * ISAR_PRE_REND_GetMultiBinPoseData() + * + * + *-------------------------------------------------------------------------*/ + +void ISAR_PRE_REND_GetMultiBinPoseData( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, /* i: Split renderer pre-renerer config */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i: Rotation axis */ +) +{ + isar_renderSplitGetMultiBinPoseData_fx( pSplit_rend_config, pMultiBinPoseData, rot_axis ); +} + +/*------------------------------------------------------------------------- + * Function ISAR_PRE_REND_MultiBinToSplitBinaural() + * + * + *------------------------------------------------------------------------*/ +ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( + SPLIT_REND_WRAPPER *hSplitBin, + const IVAS_QUATERNION headPosition, + const Word32 SplitRendBitRate, + ISAR_SPLIT_REND_CODEC splitCodec, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const Word16 isar_frame_size_ms, /* i: ISAR framesize */ +#endif + Word16 codec_frame_size_ms, + ISAR_SPLIT_REND_BITS_HANDLE pBits, + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 max_bands, + float *output[], + Word32 *pOutput_fx[], + const Word16 low_res_pre_rend_rot, + const Word16 cldfb_in_flag, + const Word16 pcm_out_flag, + const Word16 ro_md_flag, + Word16 Q_buff, + Word16 *Q_out ) +{ + ivas_error error; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int32_t bit_len, target_md_bits, available_bits, tmp_32; +#else + Word32 bit_len, target_md_bits, actual_md_bits, available_bits, tmp_32; +#endif + Word16 q1 = 31, q2 = 31, q_final, Q_cldfb, tmp, tmp_e; + Word16 i, j; + error = IVAS_ERR_OK; + Word16 Q_buff_re, Q_buff_im; + push_wmops( "ISAR_PRE_REND_MultiBinToSplitBinaural" ); +#ifdef CLDFB_SYNTH_DEBUG + /* FILE *fp = fopen( "Fixed_code_output.txt", "ab+" ); + FILE *fp1 = fopen( "Fixed_code_cldfb_state.txt", "ab+" ); + FILE *fp = fopen( "Float_code_output.txt", "ab+" ); + FILE *fp1 = fopen( "Float_code_cldfb_state.txt", "ab+" );*/ +#endif + output; + Q_buff_re = Q_buff; + move16(); + Q_buff_im = Q_buff; + move16(); + IF( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + set_fix_rotation_mat_fx( hSplitBin->hBinHrSplitPreRend->fix_pos_rot_mat_fx, &hSplitBin->multiBinPoseData ); + set_pose_types_fx( hSplitBin->hBinHrSplitPreRend->pose_type, &hSplitBin->multiBinPoseData ); + } + + IF( EQ_16( cldfb_in_flag, 0 ) ) + { + error = isar_renderMultiTDBinToSplitBinaural( hSplitBin, headPosition, SplitRendBitRate, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + isar_frame_size_ms, +#endif + codec_frame_size_ms, pBits, max_bands, pOutput_fx, Q_out[0], low_res_pre_rend_rot, pcm_out_flag, ro_md_flag ); + + pop_wmops(); + return error; + } + + IF( splitCodec == ISAR_SPLIT_REND_CODEC_LC3PLUS && hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + /* Time-align pose correction to delay of LC3plus */ + lc3plusTimeAlignCldfbPoseCorr( hSplitBin, Cldfb_In_BinReal_fx, Cldfb_In_BinImag_fx, &Q_buff ); + Q_buff_re = Q_buff; + move16(); + Q_buff_im = Q_buff; + move16(); + } + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + actual_md_bits = pBits->bits_written; +#endif + IF( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000; + +#ifndef ISAR_BITSTREAM_UPDATE_LC3PLUS + actual_md_bits = pBits->bits_written; +#endif + /*float2fix, to be removed*/ + Word16 Q_Cldfb_re = 31, Q_Cldfb_im = 31; + move16(); + move16(); + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Q_Cldfb_re = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX ), Q_Cldfb_re ); + Q_Cldfb_im = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX ), Q_Cldfb_im ); + } + } + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX, Q_Cldfb_re ); + Scale_sig32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX, Q_Cldfb_im ); + } + } + Q_buff_re = add( Q_Cldfb_re, Q_buff ); + Q_buff_im = add( Q_Cldfb_im, Q_buff ); + Word16 exp_cldfb_re = sub( 31, Q_buff_re ); + Word16 exp_cldfb_im = sub( 31, Q_buff_im ); + isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal_fx, exp_cldfb_re, Cldfb_In_BinImag_fx, exp_cldfb_im, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag ); + } + + IF( EQ_16( pcm_out_flag, 0 ) ) + { + pBits->codec = splitCodec; + pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; + + IF( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD ) + { + // available_bits = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); + available_bits = W_extract_l( W_mult0_32_32( SplitRendBitRate, L_mult0( hSplitBin->hSplitBinLCLDEnc->iNumBlocks, hSplitBin->hSplitBinLCLDEnc->iNumIterations ) ) ); + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( available_bits, L_mult0( 16, FRAMES_PER_SEC ), &tmp_e ); + available_bits = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + available_bits = L_sub( available_bits, pBits->bits_written ); +#else + actual_md_bits = L_sub( pBits->bits_written, actual_md_bits ); + available_bits = L_sub( available_bits, actual_md_bits ); +#endif + pBits->codec_frame_size_ms = codec_frame_size_ms; + q_final = sub( s_min( Q_buff_re, Q_buff_im ), 2 ); + FOR( i = 0; i < hSplitBin->hSplitBinLCLDEnc->iChannels; i++ ) + { + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); + Scale_sig32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); + } + } + isar_splitBinLCLDEncProcess( hSplitBin->hSplitBinLCLDEnc, Cldfb_In_BinReal_fx, Cldfb_In_BinImag_fx, available_bits, pBits, &q_final ); + Q_buff_re = q_final; + move16(); + Q_buff_im = q_final; + move16(); + } + ELSE + { + Word16 ch, slot_idx, num_slots, ivas_fs; + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us, 1000, &tmp_e ); + ivas_fs = shr( tmp, sub( 15, tmp_e ) ); // Q0 + // ivas_fs = (Word16) hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000; + + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( L_mult0( CLDFB_NO_COL_MAX, ivas_fs ), 20, &tmp_e ); + num_slots = shr( tmp, sub( 15, tmp_e ) ); // Q0 + // num_slots = (Word16) CLDFB_NO_COL_MAX * ivas_fs / 20; + /* CLDFB synthesis of main pose */ + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + Word32 *Cldfb_In_BinReal_p_fx[CLDFB_NO_COL_MAX]; + Word32 *Cldfb_In_BinImag_p_fx[CLDFB_NO_COL_MAX]; + q1 = 31; + q2 = 31; + move16(); + move16(); + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 ); + q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 ); + } + q_final = s_min( q1, q2 ); + q_final = s_min( add( Q_buff_re, q_final ), add( Q_buff_im, q_final ) ); + q_final = sub( q_final, 3 ); // guard bits + q_final = s_min( q_final, Q25 ); + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); + Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); + } + + FOR( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) + { + Cldfb_In_BinReal_p_fx[slot_idx] = Cldfb_In_BinReal_fx[ch][slot_idx]; + move32(); + Cldfb_In_BinImag_p_fx[slot_idx] = Cldfb_In_BinImag_fx[ch][slot_idx]; + move32(); + } + + Q_cldfb = q_final; + move16(); + Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split ) ); + cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1 + Q_out[ch] = sub( Q_cldfb, 1 ); + move16(); + hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split = Q_out[ch]; + move16(); + fixedToFloat_arrL( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state, hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length ); + } + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written; + IF( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, available_bits, pOutput_fx, Q_out[0] ) ) != IVAS_ERR_OK ) +#else + IF( ( error = splitRendLc3plusEncodeAndWrite( hSplitBin, pBits, SplitRendBitRate, pOutput_fx ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + } + } + ELSE + { + Word16 ch, slot_idx; + /* CLDFB synthesis of main pose */ + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + Word32 *Cldfb_In_BinReal_p_fx[CLDFB_NO_COL_MAX]; + Word32 *Cldfb_In_BinImag_p_fx[CLDFB_NO_COL_MAX]; + q1 = 31; + move16(); + q2 = 31; + move16(); + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 ); + q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 ); + } + q_final = s_min( q1, q2 ); + q_final = s_min( add( Q_buff_re, q_final ), add( Q_buff_im, q_final ) ); + q_final = sub( q_final, 3 ); // guard bits + q_final = s_min( q_final, Q25 ); + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); + Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); + } + + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) + { + Cldfb_In_BinReal_p_fx[slot_idx] = Cldfb_In_BinReal_fx[ch][slot_idx]; + move32(); + Cldfb_In_BinImag_p_fx[slot_idx] = Cldfb_In_BinImag_fx[ch][slot_idx]; + move32(); + } + + Q_cldfb = q_final; + move16(); + Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split ) ); + cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1 + Q_out[ch] = sub( Q_cldfb, 1 ); + move16(); + hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split = Q_out[ch]; + move16(); + } + + pBits->pose_correction = hSplitBin->multiBinPoseData.poseCorrectionMode; + pBits->codec = ISAR_SPLIT_REND_CODEC_NONE; + } + + /*zero pad*/ + IF( pcm_out_flag ) + { + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( SplitRendBitRate, FRAMES_PER_SEC, &tmp_e ); + bit_len = L_deposit_l( shr( tmp, sub( 15, tmp_e ) ) ); // Q0 + // bit_len = SplitRendBitRate / FRAMES_PER_SEC; + } + ELSE + { + IF( splitCodec == ISAR_SPLIT_REND_CODEC_LCLD ) + { + // bit_len = ( SplitRendBitRate * hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ) / ( 16 * FRAMES_PER_SEC ); + + bit_len = W_extract_l( W_mult0_32_32( SplitRendBitRate, L_mult0( hSplitBin->hSplitBinLCLDEnc->iNumBlocks, hSplitBin->hSplitBinLCLDEnc->iNumIterations ) ) ); + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( bit_len, L_mult0( 16, FRAMES_PER_SEC ), &tmp_e ); + bit_len = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 + } + ELSE + { + tmp_e = 0; + tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.isar_frame_duration_us, 1000, &tmp_e ); + bit_len = L_deposit_l( shr( tmp, sub( 15, tmp_e ) ) ); // Q0 + // bit_len = hSplitBin->hLc3plusEnc->config.ivas_frame_duration_us / 1000; + // bit_len = SplitRendBitRate * bit_len / 1000; + tmp_e = 0; + tmp_32 = BASOP_Util_Divide3232_Scale_cadence( W_extract_l( W_mult0_32_32( SplitRendBitRate, bit_len ) ), 1000, &tmp_e ); + bit_len = L_shr( tmp_32, sub( 31, tmp_e ) ); // Q0 + } + } + + WHILE( LT_32( pBits->bits_written, bit_len ) ) + { + ISAR_SPLIT_REND_BITStream_write_int32( pBits, 0L, 1 ); + } + + pop_wmops(); + /* fclose(fp); + fclose(fp1);*/ + return error; +} + +#endif diff --git a/lib_isar/lib_isar_pre_rend.h b/lib_isar/lib_isar_pre_rend.h new file mode 100644 index 000000000..fe64e4911 --- /dev/null +++ b/lib_isar/lib_isar_pre_rend.h @@ -0,0 +1,92 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef LIB_ISAR_PRE_REND_H +#define LIB_ISAR_PRE_REND_H + +#include "isar_stat.h" +#include "isar_prot.h" + +#ifndef SPLIT_REND_WITH_HEAD_ROT + +int32_t ISAR_PRE_REND_void_func( void ); + +#else +ivas_error ISAR_PRE_REND_open( + SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renerer handle */ + ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i/o: Split renderer pre-renerer config */ + const int32_t output_Fs, /* i: output sampling rate */ + const int16_t cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */ + const int16_t pcm_out_flag, /* i: Flag to indicate PCM output */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const IVAS_RENDER_FRAMESIZE ivas_frame_size, /* i: IVAS frame size */ +#else + const int16_t num_subframes, /* i: number of subframes */ +#endif + const int16_t mixed_td_cldfb_flag /* i: Flag to indicate combined TD and CLDFB input */ +); + +void ISAR_PRE_REND_close( + SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renerer handle */ + IVAS_REND_AudioBuffer *pSplitRendEncBuffer /* i/o: Split renderer data buffer */ +); + +void ISAR_PRE_REND_GetMultiBinPoseData( + const ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, /* i: Split renderer pre-renerer config */ + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, /* i/o: pose correction data handle */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i: Rotation axis */ +); + +ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( + SPLIT_REND_WRAPPER *hSplitBin, /* i/o: Split renderer pre-renerer handle */ + const IVAS_QUATERNION headPosition, /* i: head rotation QUATERNION */ + const Word32 SplitRendBitRate, /* i: Split renderer bitrate */ + ISAR_SPLIT_REND_CODEC splitCodec, /* i/o: Split renderer codec */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + const Word16 isar_frame_size_ms, /* i: ISAR framesize */ +#endif + Word16 codec_frame_size_ms, /* i/o: Split renderer codec framesize */ + ISAR_SPLIT_REND_BITS_HANDLE pBits, /* i/o: Split renderer bitstream handle */ + Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */ + Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */ + const Word16 max_bands, /* i: CLDFB bands */ + float *output[], /* i/o: PCM in/out buffer */ + Word32 *pOutput_fx[], /* i: low time resolution pre-renderer flag */ + const Word16 low_res_pre_rend_rot, /* i: low time resolution pre-renderer flag */ + const Word16 cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */ + const Word16 pcm_out_flag, /* i: Flag to indicate PCM output */ + const Word16 ro_md_flag, /* i: Flag to indicate real only metadata for yaw */ + Word16 Q_buff, + Word16 *Q_out ); + +#endif +#endif /* LIB_ISAR_PRE_REND_H */ diff --git a/lib_lc3plus/.clang-format b/lib_lc3plus/.clang-format new file mode 100644 index 000000000..47a38a93f --- /dev/null +++ b/lib_lc3plus/.clang-format @@ -0,0 +1,2 @@ +DisableFormat: true +SortIncludes: Never diff --git a/lib_lc3plus/adjust_global_gain_fx.c b/lib_lc3plus/adjust_global_gain_fx.c new file mode 100644 index 000000000..c6067b591 --- /dev/null +++ b/lib_lc3plus/adjust_global_gain_fx.c @@ -0,0 +1,186 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + + + +void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx_off, +#ifdef ENABLE_HR_MODE + Word32 *gain, +#else + Word16 *gain, +#endif + Word16 *gain_e, + Word16 target, Word16 nBits, Word16 *gainChange, Word16 fs_idx +#ifdef ENABLE_HR_MODE + , Word16 hrmode, Word16 frame_dms +#endif + ) +{ + + Word32 L_tmp; + Word16 delta, delta2; +#ifdef ENABLE_HR_MODE + Word16 gg_idx_inc; + Word16 gg_idx_inc_max; + Word16 gg_idx_inc_s; +# ifdef CR8_G_ADD_75MS + Word32 factor; +# else + Word16 factor; +# endif +#endif + +#ifdef DYNMEM_COUNT +#if defined(ENABLE_HR_MODE) + Dyn_Mem_In("processAdjustGlobalGain_fx", sizeof(struct { + Word32 L_tmp; + Word16 delta, delta2; + Word16 gg_idx_inc; + Word16 gg_idx_inc_max; + Word16 gg_idx_inc_s; + Word16 factor; + })); +#else + Dyn_Mem_In("processAdjustGlobalGain_fx", sizeof(struct { + Word32 L_tmp; + Word16 delta, delta2; + })); +#endif /* ENABLE_HR_MODE */ +#endif /* DYNMEM_COUNT */ + +#ifdef ENABLE_HR_MODE + IF (sub(frame_dms, 25) == 0) + { + IF (sub(target, 520) < 0) + { + factor = 3; move16(); + gg_idx_inc_max = 30; move16(); + } ELSE { + factor = 4; move16(); + gg_idx_inc_max = 40; move16(); + } + } + ELSE IF (sub(frame_dms, 50) == 0) + { + factor = 2; move16(); + gg_idx_inc_max = 20; move16(); + } +#ifdef CR8_G_ADD_75MS + ELSE IF (sub(frame_dms, 75) == 0) + { + factor = 40265318; move16(); // factor = 1.2 * 2^25 + gg_idx_inc_max = 12 ; move16(); + } +#endif + ELSE + { + factor = 1; move16(); + gg_idx_inc_max = 10; move16(); + } +#endif + + IF (sub(nBits, adjust_global_gain_tables[0][fs_idx]) < 0) + { + delta = mult_r(add(nBits, 48), 2048); + } + ELSE IF (sub(nBits, adjust_global_gain_tables[1][fs_idx]) < 0) + { + delta = mult_r(add(nBits, adjust_global_gain_tables[4][fs_idx]), adjust_global_gain_tables[3][fs_idx]); + } + ELSE IF (sub(nBits, adjust_global_gain_tables[2][fs_idx]) < 0) + { + delta = mult_r(nBits, 683); + } + ELSE + { + delta = mult_r(adjust_global_gain_tables[2][fs_idx], 683); + } + delta2 = add(delta, 2); + + *gainChange = 0; move16(); + + test(); + IF (sub(*gg_idx, 255) == 0 && sub(nBits, target) > 0) + { + *gainChange = 1; move16(); + } + + test(); test(); test(); + IF ((sub(*gg_idx, 255) < 0 && sub(nBits, target) > 0) || (*gg_idx > 0 && sub(nBits, sub(target, delta2)) < 0)) + { +#ifdef ENABLE_HR_MODE + IF (hrmode) + { + IF (sub(nBits, target) > 0) + { + gg_idx_inc = sub(nBits, target); +#ifdef CR8_G_ADD_75MS + IF (sub(frame_dms, 75) == 0) + { + gg_idx_inc = extract_l(L_shr_pos(Mpy_32_16_lc3plus(factor, gg_idx_inc), 10)); // Mpy_32_16_lc3plus(1.2*2^25, gg_idx_inc), 25 - 15) + gg_idx_inc = BASOP_Util_Divide1616_Scale_lc3plus(gg_idx_inc, delta, &gg_idx_inc_s); + gg_idx_inc = shr_sat(gg_idx_inc, sub(15, gg_idx_inc_s)); + gg_idx_inc = add(gg_idx_inc, 1); // adding 1 instead of 1.2 + } + ELSE +#endif + { + gg_idx_inc = extract_l(L_mult0(gg_idx_inc, factor)); + gg_idx_inc = BASOP_Util_Divide1616_Scale_lc3plus(gg_idx_inc, delta, &gg_idx_inc_s); + gg_idx_inc = shr_sat(gg_idx_inc, sub(15, gg_idx_inc_s)); + gg_idx_inc = add(gg_idx_inc, factor); + } + gg_idx_inc = s_min(gg_idx_inc, gg_idx_inc_max); + + *gg_idx = add(*gg_idx, gg_idx_inc); move16(); + } + + *gg_idx = s_min(*gg_idx, 255); move16(); + } + ELSE +#endif + { + test(); + IF (sub(nBits, sub(target, delta2)) < 0) + { + *gg_idx = sub(*gg_idx, 1); move16(); + } + ELSE IF (sub(*gg_idx, 254) == 0 || sub(nBits, add(target, delta)) < 0) + { + *gg_idx = add(*gg_idx, 1); move16(); + } + ELSE + { + *gg_idx = add(*gg_idx, 2); move16(); + } + } + + *gg_idx = s_max(*gg_idx, sub(gg_idx_min, gg_idx_off)); move16(); + +#ifdef ENABLE_HR_MODE + L_tmp = Mpy_32_16_lc3plus(0x3CBE6B83, L_shl_pos(add(*gg_idx, gg_idx_off), 7)); +#else + L_tmp = L_shl_pos(L_mult0(add(*gg_idx, gg_idx_off), 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ +#endif + *gain_e = add(extract_l(L_shr_pos(L_tmp, 25)), 1); /* get exponent */ +#ifdef ENABLE_HR_MODE + *gain = BASOP_Util_InvLog2_lc3plus(L_or(L_tmp, (Word32)0xFE000000)); +#else + *gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(L_tmp, (Word32)0xFE000000))); +#endif + *gainChange = 1; move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/al_fec.c b/lib_lc3plus/al_fec.c new file mode 100644 index 000000000..7579a21b0 --- /dev/null +++ b/lib_lc3plus/al_fec.c @@ -0,0 +1,2379 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" + + +#include "functions.h" +#include "rom_basop_util.h" +#include +#include +#include +#include + +/* channel coder specific constants and macros */ +#define RS16_CW_LEN_MAX 15 + +#define FEC_N_MODES 4 +#define FEC_N_SYNDROMES_MAX 6 +#define FEC_N_ERR_POS_MAX 3 +#define FEC_N_ELP_COEFF_MAX 4 +#define FEC_N_ERR_SYMB_MAX 3 +#define FEC_N_MODE_DETECTION_CW 6 + +#define SYNDROME_IDX(mode_index, cw_index) (((mode_index)*FEC_N_MODE_DETECTION_CW + (cw_index)) * FEC_N_SYNDROMES_MAX) +#define ELP_IDX(mode_index, cw_index) (((mode_index)*FEC_N_MODE_DETECTION_CW + (cw_index)) * FEC_N_ELP_COEFF_MAX) +#define ERR_POS_IDX(mode_index, cw_index) (((mode_index)*FEC_N_MODE_DETECTION_CW + (cw_index)) * FEC_N_ERR_POS_MAX) +#define ERR_SYMB_IDX(mode_index, cw_index) (((mode_index)*FEC_N_MODE_DETECTION_CW + (cw_index)) * FEC_N_ERR_SYMB_MAX) +#define DEG_ELP_IDX(mode_index, cw_index) ((mode_index)*FEC_N_MODE_DETECTION_CW + (cw_index)) + +#define FEC_TOTAL_SYNDROME_SIZE (FEC_N_SYNDROMES_MAX * FEC_N_MODES * FEC_N_MODE_DETECTION_CW) +#define FEC_TOTAL_ELP_SIZE (FEC_N_ELP_COEFF_MAX * FEC_N_MODES * FEC_N_MODE_DETECTION_CW) +#define FEC_TOTAL_ERR_POS_SIZE (FEC_N_ERR_POS_MAX * FEC_N_MODES * FEC_N_MODE_DETECTION_CW) +#define FEC_TOTAL_ERROR_SIZE (FEC_N_ERR_SYMB_MAX * FEC_N_MODES * FEC_N_MODE_DETECTION_CW) +#define FEC_TOTAL_DEG_ELP_SIZE (FEC_N_MODES * FEC_N_MODE_DETECTION_CW) + +#define ERROR_REPORT_BEC_MASK ((0x0FFF)>>1) +#define ERROR_REPORT_EP1_OK ((0x1000)>>1) +#define ERROR_REPORT_EP2_OK ((0x2000)>>1) +#define ERROR_REPORT_EP3_OK ((0x4000)>>1) +#define ERROR_REPORT_EP4_OK ((0x8000)>>1) +#define ERROR_REPORT_ALL_OK (ERROR_REPORT_EP1_OK | ERROR_REPORT_EP2_OK | ERROR_REPORT_EP3_OK | ERROR_REPORT_EP4_OK) + +/* debugging switches */ + +/* constants concerning mode detection */ +#define EP_RISK_THRESH_NS_M 21990 +#define EP_RISK_THRESH_NS_E -23 +#define EP_RISK_THRESH_OS_M 25166 +#define EP_RISK_THRESH_OS_E -10 + +#define SIMPLE_FLOAT_1_MANTISSA 16384 + +#define FEC_STATIC static + +/* DISCLAIMER: Strict instrumentation of GF16 arithmetic would have to take into account + * the initial conversion of the arguments from UWord8 to Word16 (one move16() per argument). + * Behind this is the assumption that one would store GF16 elements in Word16 for strict BASOP + * implementation. + */ + +#define GF16_MUL(a, b) (UWord8)(move16(), gf16_mult_table[s_or((a), shl((b), 4))]) +#define GF16_MUL0(a, b) (UWord8)(move16(), gf16_mult_table[s_or((a), (b))]) +#define GF16_ADD(a, b) (UWord8) s_xor((a), (b)) + +/* tables for finite field arithmetic */ +/* tables for arithmetic in GF(16) * + * generator polynomial: 19 + * unit group generator (g): 2 + */ + +static const UWord8 gf16_g_pow[16] = {1, 2, 4, 8, 3, 6, 12, 11, 5, 10, 7, 14, 15, 13, 9, 1}; +/* g_pow[i] contains g^i*/ + +static const UWord8 gf16_log_g[16] = {255, 0, 1, 4, 2, 8, 5, 10, 3, 14, 9, 7, 6, 13, 11, 12}; +/* log_g[n] contains contains the value i such that g^i = n for n=1, 2, ..., 15, log_g[0] is set to 255 */ + +static const UWord8 gf16_inv_table[16] = {255, 1, 9, 14, 13, 11, 7, 6, 15, 2, 12, 5, 10, 4, 3, 8}; +/* gf16_inv_table[n] contains the multiplicative inverse of n in GF(16) (1/0 is set to 255)*/ + +/* RS16 generating polynomials (from lowest to highest coefficient without leading 1)*/ + +static const UWord8 rs16_gp_d3[] = {8, 6}; +static const UWord8 rs16_gp_d5[] = {7, 8, 12, 13}; +static const UWord8 rs16_gp_d7[] = {12, 10, 12, 3, 9, 7}; + +/* FEC mode signaling polynomials */ + +#define EP_SIG_POLY_DEG 12 + +static const UWord8 sig_polys[4][15] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {7, 15, 5, 6, 14, 9, 1, 3, 12, 10, 13, 3, 2, 0, 0}, + {7, 11, 14, 1, 2, 3, 12, 11, 6, 15, 7, 6, 12, 0, 0}, + {6, 15, 12, 2, 9, 15, 2, 8, 12, 3, 10, 5, 4, 0, 0}}; + +static const UWord8 sig_poly_syndr[4][6] = { + {0, 0, 0, 0, 0, 0}, {0, 4, 5, 11, 5, 8}, {0, 5, 9, 0, 1, 7}, {0, 12, 5, 12, 9, 8}}; + +/* bit count table for error report (0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111) */ + +static const UWord8 rs16_bit_count_table[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; + +/* List of RS16 generators by Hamming distance */ + +static const UWord8 *const rs16_gp_by_hd[8] = {NULL, NULL, NULL, rs16_gp_d3, NULL, rs16_gp_d5, NULL, rs16_gp_d7}; + +/* fec config data */ + +static const UWord8 hamming_distance_by_mode0[] = {1, 3, 3, 5, 7}; +static const UWord8 hamming_distance_by_mode1[] = {1, 1, 3, 5, 7}; + +static const UWord8 crc1_bytes_by_mode0[] = {0, 3, 2, 2, 2}; +static const UWord8 crc1_bytes_by_mode1[] = {0, 3, 3, 3, 3}; +static const UWord8 crc2_bytes_by_mode[] = {0, 0, 2, 2, 2}; + +/* fec mode risk table */ +typedef struct +{ + UWord32 mantissa; + Word16 exponent; +} simple_float; + +static const simple_float risk_table_f[4][4] = {{{16384, 0}, {16384, 0}, {16384, 0}, {16384, 0}}, + {{16384, -8}, {26880, -1}, {16384, 0}, {16384, 0}}, + {{16384, -16}, {26880, -9}, {20475, -2}, {16384, 0}}, + {{16384, -24}, {26880, -17}, {20475, -10}, {19195, -4}}}; +/* bit error limits for slot size 40 */ +static Word16 const low_br_max_bit_errors_by_mode[] = {0, 0, 3, 9, 18}; + +/* +corresponding float values: + {1.f, 1.f, 1.f, 1.f}, + {0.00390625f, 0.820312f, 1.f, 1.f}, + {1.52588e-05f, 0.00320435f, 0.312424f, 1.f}, + {5.96046e-08f, 1.2517e-05f, 0.00122041f, 0.0732243f} +*/ + +/* internal encoder routines */ + +FEC_STATIC void fec_interleave_pack(UWord8 *out, UWord8 *in, Word16 n_nibbles, Word16 n_codewords); + +FEC_STATIC void rs16_enc(UWord8 *iobuf, Word16 codeword_length, Word16 hamming_distance, Word16 fec_mode, + Word16 signal_mode); + +/* internal decoder routines */ + +FEC_STATIC void fec_deinterleave_unpack(UWord8 *out, UWord8 *in, Word16 n_nibbles, Word16 n_codewords); + +FEC_STATIC Word16 fec_data_preproc(Word16 mode, Word16 epmr, UWord8 *iobuf, UWord8 *cw_buf, Word16 data_bytes, + Word16 slot_bytes, Word16 pc_split); + +FEC_STATIC void fec_data_postproc(Word16 mode, Word16 *epmr, UWord8 *iobuf, Word16 data_bytes, UWord8 *cw_buf, + Word16 slot_bytes, Word16 pc_split, int *bfi); + +FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codewords, Word16 *epmr, Word16 *error_report, + int *bfi, UWord8 *array_of_trust, int ccc_flag_flag, Word16 *n_pccw, void *scratch); + +FEC_STATIC void rs16_calculate_six_syndromes(UWord8 *syndromes, UWord8 *cw, int cw_poly_deg); + +FEC_STATIC void rs16_calculate_four_syndromes(UWord8 *syndromes, UWord8 *cw, int cw_poly_deg); + +FEC_STATIC void rs16_calculate_two_syndromes(UWord8 *syndromes, UWord8 *cw, int cw_poly_deg); + +FEC_STATIC Word8 rs16_calculate_elp(UWord8 *elp, UWord8 *syndromes, Word16 hamming_distance); + +FEC_STATIC Word16 rs16_factorize_elp(UWord8 *error_locations, UWord8 *elp, Word16 deg_elp, Word16 max_pos); + +FEC_STATIC void rs16_calculate_errors(UWord8 *errors, UWord8 *err_pos, UWord8 *syndromes, Word8 deg_elp, Word8 t); + +/* auxiliary routines */ + +FEC_STATIC Word16 crc1(UWord8 *data, Word16 data_size, Word16 epmr, UWord8 *hash, Word16 hash_size, Word16 check); + +FEC_STATIC Word16 fec_estimate_epmr_from_cw0(UWord8 *cw0, Word8 *t, UWord8 *syndromes, UWord8 *elp, Word8 *deg_elp, + UWord8 *err_pos, UWord8 *err_symb, Word16 n_codewords, Word16 n_symb); + +FEC_STATIC void dw0_bitswap(UWord8 *dw0, Word16 mode, Word16 slot_bytes); + +FEC_STATIC Word16 cw0_get_epmr(UWord8 *cw0, Word16 epmr_position); + +FEC_STATIC Word16 dw0_get_epmr(UWord8 *dw0, Word16 mode, Word16 slot_size); + +FEC_STATIC Word16 crc2(UWord8 *data, Word16 data_size, UWord8 *hash, Word16 hash_size, Word16 check); + +FEC_STATIC simple_float simple_float_mul(simple_float op1, simple_float op2); + +FEC_STATIC Word16 simple_float_cmp(simple_float op1, simple_float op2); + +FEC_STATIC Word16 get_total_crc_size(Word16 slot_bytes, Word16 fec_mode, Word16 pc_split); + +FEC_STATIC Word16 get_n_codewords(Word16 slot_bytes); + +FEC_STATIC Word16 get_codeword_length(Word16 n_codewords, Word16 slot_nibbles, Word16 codeword_index); + + + +Word16 fec_get_n_pccw(Word16 slot_bytes, Word16 fec_mode, Word16 ccc_flag) +{ + Dyn_Mem_Deluxe_In( + Word16 n_pccw; + ); + + IF (sub(fec_mode, 3) == 0) + { + n_pccw = round_fx(L_sub(L_mult(2636, slot_bytes), 117377)); + } + ELSE IF (sub(fec_mode, 4) == 0) + { + n_pccw = round_fx(L_sub(L_mult(2178, slot_bytes), 129115)); + } + ELSE + { + n_pccw = 0; move16(); + } + + if (ccc_flag == 1 || sub(slot_bytes, 80) < 0) + { + n_pccw = 0; move16(); + } + + Dyn_Mem_Deluxe_Out(); + return n_pccw; +} + +FEC_STATIC Word16 get_total_crc_size(Word16 slot_bytes, Word16 fec_mode, Word16 pc_split) +{ + Dyn_Mem_Deluxe_In( + Word16 n_crc; + ); + + n_crc = crc1_bytes_by_mode1[fec_mode]; move16(); + if (sub(slot_bytes, 40) == 0) + { + n_crc = crc1_bytes_by_mode0[fec_mode]; move16(); + } + + IF (pc_split > 0) + { + n_crc = add(n_crc, crc2_bytes_by_mode[fec_mode]); + } + Dyn_Mem_Deluxe_Out(); + return n_crc; +} + +FEC_STATIC Word16 get_n_codewords(Word16 slot_bytes) +{ + Dyn_Mem_Deluxe_In( + Word16 i; + ); + + slot_bytes = shl(slot_bytes, 1); + + FOR (i = 0; slot_bytes > 0; i++) + { + slot_bytes = sub(slot_bytes, RS16_CW_LEN_MAX); + } + + Dyn_Mem_Deluxe_Out(); + return i; +} + +FEC_STATIC Word16 get_codeword_length(Word16 n_codewords, Word16 slot_nibbles, Word16 codeword_index) +{ + Dyn_Mem_Deluxe_In( + Word16 i; + ); + + slot_nibbles = sub(slot_nibbles, add(codeword_index, 1)); + slot_nibbles = sub(slot_nibbles, DEPR_i_mult(n_codewords, 13)); + + FOR (i = 12; slot_nibbles >= 0; i++) + { + slot_nibbles = sub(slot_nibbles, n_codewords); + } + + Dyn_Mem_Deluxe_Out(); + return add(i, 1); +} + +/* Encoder */ + +Word16 fec_get_data_size(Word16 fec_mode, Word16 ccc_flag, Word16 slot_bytes) +/* not time critical */ +{ + Dyn_Mem_Deluxe_In( + Word16 n_codewords, payload_size; + ); + + n_codewords = get_n_codewords(slot_bytes); + + assert(n_codewords == (2 * slot_bytes + RS16_CW_LEN_MAX - 1) / RS16_CW_LEN_MAX); + payload_size = slot_bytes; move16(); + + IF (fec_mode > 0) + { + IF (fec_mode == 1) + { + payload_size = sub(payload_size, 1); + } + ELSE + { + payload_size = sub(payload_size, DEPR_i_mult(sub(fec_mode, 1), n_codewords)); + } + IF (slot_bytes == 40) + { + payload_size = sub(payload_size, crc1_bytes_by_mode0[fec_mode]); move16(); + } + ELSE + { + payload_size = sub(payload_size, crc1_bytes_by_mode1[fec_mode]); move16(); + } + + IF (ccc_flag == 0 && fec_mode > 2 && slot_bytes >= 80) + { + payload_size = sub(payload_size, crc2_bytes_by_mode[fec_mode]); + } + } + + Dyn_Mem_Deluxe_Out(); + return payload_size; +} + +Word16 fec_get_n_pc(Word16 fec_mode, Word16 n_pccw, Word16 slot_bytes) +/* not time critical */ +{ + Dyn_Mem_Deluxe_In( + Word16 n_codewords, pc_split, tmp; + int i; + ); + + n_codewords = get_n_codewords(slot_bytes); + + assert(n_codewords == (2 * slot_bytes + RS16_CW_LEN_MAX - 1) / RS16_CW_LEN_MAX); + pc_split = DEPR_i_mult(DEPR_i_mult(n_pccw, -2), sub(fec_mode, 1)); + + IF (fec_mode == 1 || slot_bytes < 80) + { + pc_split = 0; move16(); + } + ELSE + { + FOR (i = 0; i < n_pccw; i++) + { + tmp = get_codeword_length(n_codewords, add(slot_bytes, slot_bytes), sub(n_codewords, i + 1)); + assert(tmp == (2 * slot_bytes + i) / n_codewords); + pc_split = add(pc_split, tmp); + } + } + + Dyn_Mem_Deluxe_Out(); + return pc_split; +} + +/* functions for EPMR handling */ +FEC_STATIC void dw0_bitswap(UWord8 *dw0, Word16 mode, Word16 slot_bytes) +/* swap epmr bits with bits that will be positioned at 30 and 32 in code word 0 */ +{ + Dyn_Mem_Deluxe_In( + UWord8 tmp; + int ind0, ind1, position; + ); + + position = sub(get_codeword_length(get_n_codewords(slot_bytes), shl(slot_bytes, 1), 0), 1); + + IF (sub(slot_bytes, 40) == 0) + { + ind0 = sub(shl(crc1_bytes_by_mode0[mode], 1), 1); + } + ELSE + { + ind0 = sub(shl(crc1_bytes_by_mode1[mode], 1), 1); + } + + ind1 = sub(position, sub(hamming_distance_by_mode0[mode], 1)); + + /* swap bits 2 and 3 of dw0[ind0] with bits 0 and 1 of dw0[ind1] */ + tmp = (UWord8) s_and(shr(dw0[ind0],2), 3); + dw0[ind0] = (UWord8) s_and(dw0[ind0], 3); + dw0[ind0] = (UWord8) s_or(dw0[ind0], shl(s_and(dw0[ind1], 3),2)); + dw0[ind1] = (UWord8) s_and(dw0[ind1], 12); + dw0[ind1] = (UWord8) s_or(dw0[ind1], tmp); + + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC Word16 cw0_get_epmr(UWord8 *cw0, Word16 position) +{ + Dyn_Mem_Deluxe_In( + Word16 epmr; + ); + epmr = s_and(cw0[position], 3); + + Dyn_Mem_Deluxe_Out(); + return epmr; +} + +FEC_STATIC Word16 dw0_get_epmr(UWord8 *dw0, Word16 mode, Word16 slot_size) +{ + Dyn_Mem_Deluxe_In( + int ncrc1; + Word16 epmr; + ); + + ncrc1 = crc1_bytes_by_mode1[mode]; + + if (sub(slot_size, 40) == 0) + { + ncrc1 = crc1_bytes_by_mode0[mode]; + } + + epmr = shr(dw0[2 * ncrc1 - 1], 2); + + Dyn_Mem_Deluxe_Out(); + return epmr; +} + + +FEC_STATIC Word16 fec_data_preproc(Word16 mode, Word16 epmr, UWord8 *iobuf, UWord8 *cw_buf, Word16 data_bytes, + Word16 slot_bytes, Word16 pc_split) +{ + Dyn_Mem_Deluxe_In( + Word16 data_offset, n_crc1, n_crc2, tmp; + int i, j; + ); + + tmp = sub(slot_bytes, data_bytes); + data_offset = add(tmp, tmp); + + /* extract and reverse data*/ + j = sub(add(slot_bytes, slot_bytes), 1); + FOR (i = 0; i < data_bytes; i++) + { + cw_buf[j--] = (UWord8)s_and(iobuf[i], 15); move16(); + cw_buf[j--] = (UWord8)shr(iobuf[i], 4); move16(); + } + + /* add crc hashes */ + IF (sub(slot_bytes, 40) == 0) + { + n_crc1 = crc1_bytes_by_mode0[mode]; move16(); + } + ELSE + { + n_crc1 = crc1_bytes_by_mode1[mode]; move16(); + } + + IF (pc_split > 0 && sub(mode, 1) > 0) + { + n_crc2 = crc2_bytes_by_mode[mode]; move16(); + } + ELSE + { + n_crc2 = 0; move16(); + } + + IF (n_crc2) + { + crc2(cw_buf + data_offset + 2 * data_bytes - pc_split, pc_split, cw_buf + data_offset - 2 * n_crc2, n_crc2, 0); + } + IF (n_crc1) + { + crc1(cw_buf + data_offset, 2 * data_bytes - pc_split, epmr, cw_buf + data_offset - 2 * (n_crc1 + n_crc2), n_crc1, + 0); + } + + tmp = add(n_crc1, n_crc2); + data_offset = sub(data_offset, add(tmp, tmp)); + + dw0_bitswap(cw_buf + data_offset, mode, slot_bytes); + + Dyn_Mem_Deluxe_Out(); + return data_offset; +} + +void fec_encoder(Word16 mode, Word16 epmr, UWord8 *iobuf, Word16 data_bytes, Word16 slot_bytes, Word16 n_pccw, + void *scratch) +{ + Dyn_Mem_Deluxe_In( + Word16 n_codewords, codeword_length, hd, redundancy_nibbles, cw_offset, dw_offset, pc_split; + int i, j; + UWord8 *cw_buf; + ); + + cw_offset = 0; move16(); + dw_offset = 0; move16(); + pc_split = 0; move16(); + cw_buf = scratch; + + n_codewords = get_n_codewords(slot_bytes); + assert(n_codewords == (2 * slot_bytes + RS16_CW_LEN_MAX - 1) / RS16_CW_LEN_MAX); + + /* some sanity checks */ + { + int tmp = slot_bytes; + assert((slot_bytes >= FEC_SLOT_BYTES_MIN && slot_bytes <= FEC_SLOT_BYTES_MAX) && + "fec_encoder: slot_bytes out of range"); + tmp -= mode == 1 ? 1 : n_codewords * (mode - 1); // reed solomon redundancy + tmp -= slot_bytes == 40 ? crc1_bytes_by_mode0[mode] : crc1_bytes_by_mode1[mode]; // crc1 + tmp -= (n_pccw > 0) && (mode > 1) ? crc2_bytes_by_mode[mode] : 0; // crc2 + assert(data_bytes == tmp && "fec_encoder: inconsistent payload size"); + assert(n_codewords - n_pccw >= 6); + } + + /* data preproc: re-ordering and hash extension */ + pc_split = fec_get_n_pc(mode, n_pccw, slot_bytes); + + dw_offset = fec_data_preproc(mode, epmr, iobuf, cw_buf, data_bytes, slot_bytes, pc_split); + + /* encoding of first data word*/ + hd = hamming_distance_by_mode0[mode]; move16(); + redundancy_nibbles = sub(hd, 1); + codeword_length = get_codeword_length(n_codewords, add(slot_bytes, slot_bytes), 0); + + assert(codeword_length == (2 * slot_bytes - 1) / n_codewords + 1); + + FOR (j = redundancy_nibbles; j < codeword_length; (j++, dw_offset++)) + { + cw_buf[j] = cw_buf[dw_offset]; move16(); + } + + rs16_enc(cw_buf, codeword_length, hd, mode, 1); + + cw_offset = add(cw_offset, codeword_length); + + /* encoding of remaining data words */ + hd = hamming_distance_by_mode1[mode]; move16(); + redundancy_nibbles = sub(hd, 1); + + FOR (i = 1; i < n_codewords; i++) + { + codeword_length = get_codeword_length(n_codewords, add(slot_bytes, slot_bytes), i); + + assert(codeword_length == (2 * slot_bytes - i - 1) / n_codewords + 1); + FOR (j = redundancy_nibbles; j < codeword_length; (j++, dw_offset++)) + { + cw_buf[cw_offset + j] = cw_buf[dw_offset]; move16(); + } + + rs16_enc(cw_buf + cw_offset, codeword_length, hd, mode, sub(i, 6) < 0); + + cw_offset = add(cw_offset, codeword_length); + } + + assert(cw_offset == 2 * slot_bytes && dw_offset == 2 * slot_bytes); + + fec_interleave_pack(iobuf, cw_buf, add(slot_bytes, slot_bytes), n_codewords); + + + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC void rs16_enc(UWord8 *iobuf, Word16 codeword_length, Word16 hamming_distance, Word16 fec_mode, + Word16 signal_mode) +/* expects (data polynomial) * x^(hamming_distance - 1) in iobuf */ +{ + + Dyn_Mem_Deluxe_In( + UWord8 const *gp; + UWord8 shift_buffer[RS16_CW_LEN_MAX + 1], lc; + int i, j, deg_gp; + ); + + basop_memset(shift_buffer, 0, sizeof(shift_buffer)); + gp = rs16_gp_by_hd[hamming_distance]; move16(); + deg_gp = sub(hamming_distance, 1); + + IF (sub(hamming_distance, 1) > 0) + { + assert(codeword_length > deg_gp); + + /* initialize redundancy part to zero */ + basop_memset(iobuf, 0, deg_gp); + + /* initialize shift_buffer */ + basop_memmove(shift_buffer + 1, iobuf + codeword_length - deg_gp, deg_gp); + + /* calculate remainder */ + FOR (i = codeword_length - deg_gp - 1; i >= 0; i--) + { + shift_buffer[0] = iobuf[i]; move16(); + lc = (UWord8)shl(shift_buffer[deg_gp], 4); move16(); + FOR (j = deg_gp - 1; j >= 0; j--) + { + shift_buffer[j + 1] = GF16_ADD(shift_buffer[j], GF16_MUL0(gp[j], lc)); move16(); + } + } + + /* add remainder to shifted data polynomial */ + FOR (i = 0; i < deg_gp; i++) + { + iobuf[i] = shift_buffer[i + 1]; move16(); + } + + /* add signaling polynomial */ + IF (signal_mode) + { + assert(codeword_length > EP_SIG_POLY_DEG); + FOR (i = 0; i <= EP_SIG_POLY_DEG; i++) + { + iobuf[i] = GF16_ADD(iobuf[i], sig_polys[fec_mode - 1][i]); move16(); + } + } + } + + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC void fec_interleave_pack(UWord8 *out, UWord8 *in, Word16 n_nibbles, Word16 n_codewords) +{ + Dyn_Mem_Deluxe_In( + Word16 out_offset, cw_offset, codeword_length; + int i, j; + ); + + out_offset = 0; move16(); + cw_offset = 0; move16(); + + /* initialize output buffer to zero */ + basop_memset(out, 0, shr(n_nibbles, 1)); + + /* interleave and pack codewords */ + FOR (i = 0; i < n_codewords; i++) + { + codeword_length = get_codeword_length(n_codewords, n_nibbles, i); + + assert(codeword_length == (n_nibbles - i - 1) / n_codewords + 1); + FOR (j = 0; j < codeword_length; j++) + { + out_offset = add(DEPR_i_mult(j, n_codewords), i); + out_offset = sub(n_nibbles, add(out_offset, 1)); + out[out_offset >> 1] = + (UWord8)s_or(out[out_offset >> 1], shl(in[cw_offset], shl(s_and(out_offset, 1), 2))); move16(); + cw_offset = add(cw_offset, 1); + } + } + + assert(cw_offset == n_nibbles); + Dyn_Mem_Deluxe_Out(); +} + +/* Decoder */ +FEC_STATIC void fec_data_postproc(Word16 mode, Word16 *epmr, UWord8 *obuf, Word16 data_bytes, UWord8 *cw_buf, + Word16 slot_bytes, Word16 pc_split, int *bfi) +{ + Dyn_Mem_Deluxe_In( + Word16 i; + Word16 n_crc1, n_crc2; + Word16 cw_buf_len; + Word16 tmp_epmr; + ); + + n_crc1 = crc1_bytes_by_mode1[mode]; move16(); + if (sub(slot_bytes, 40) == 0) + { + n_crc1 = crc1_bytes_by_mode0[mode]; move16(); + } + + n_crc2 = 0; move16(); + if (pc_split > 0) + { + n_crc2 = crc2_bytes_by_mode[mode]; move16(); + } + + assert(n_crc1 == (slot_bytes == 40 ? crc1_bytes_by_mode0[mode] : crc1_bytes_by_mode1[mode])); + assert(n_crc2 == ((pc_split > 0) && (mode > 1) ? crc2_bytes_by_mode[mode] : 0)); + + cw_buf_len = 2 * (data_bytes + n_crc1 + n_crc2); + + IF (sub(mode, 1)) + { + /* reverse bit-swap */ + dw0_bitswap(cw_buf, mode, slot_bytes); + tmp_epmr = dw0_get_epmr(cw_buf, mode, slot_bytes); + + IF (crc1(cw_buf + shl(add(n_crc1, n_crc2), 1), sub(shl(data_bytes, 1), pc_split), tmp_epmr, cw_buf, n_crc1, 1)) + { + *bfi = 1; move32(); + + Dyn_Mem_Deluxe_Out(); + return; + } + else + { + *epmr = tmp_epmr; + } + } + + test(); + IF (pc_split > 0 && sub(*bfi, 2) != 0) + { + IF (crc2(cw_buf + sub(shl(add(data_bytes, add(n_crc1, n_crc2)), 1), pc_split), pc_split, + cw_buf + shl(n_crc1, 1), n_crc2, 1)) + { + *bfi = 2; move32(); + } + } + + FOR (i = 0; i < data_bytes; i++) + { + obuf[i] = (UWord8)s_or(cw_buf[cw_buf_len - 2 * i - 1], shl(cw_buf[cw_buf_len - 2 * i - 2], 4)); move16(); + } + Dyn_Mem_Deluxe_Out(); +} + +int fec_decoder(UWord8 *iobuf, Word16 slot_bytes, int *data_bytes, Word16 *epmr, Word16 ccc_flag, Word16 *n_pccw, + int *bfi, Word16 *be_bp_left, Word16 *be_bp_right, Word16 *n_pc, Word16 *m_fec, void *scratch) +{ + Dyn_Mem_Deluxe_In( + UWord8 *my_scratch; + UWord8 *cw_buf; + UWord8 *array_of_trust; + Word16 i, j; + Word16 cw_offset, dw_offset; + Word16 n_codewords, redundancy_nibbles, codeword_length; + Word16 mode, error_report; + Word16 n_crc; + Word16 first_bad_cw; + Word16 pc_split; + ); + + IF (*bfi == 1) + { + Dyn_Mem_Deluxe_Out(); + return ERROR_REPORT_BEC_MASK; + } + + if (slot_bytes < FEC_SLOT_BYTES_MIN || slot_bytes > FEC_SLOT_BYTES_MAX) + { + *bfi = 1; + return ERROR_REPORT_BEC_MASK; + } + + my_scratch = (UWord8 *)scratch; move32(); + cw_buf = my_scratch; move32(); + my_scratch += 2 * slot_bytes; + + IF (ccc_flag == 0) + { + *be_bp_left = -1; move16(); + *be_bp_right = -1; move16(); + } + + n_codewords = get_n_codewords(slot_bytes); + + array_of_trust = my_scratch; move32(); + my_scratch += n_codewords; + + /* extract and de-interleave nibbles */ + fec_deinterleave_unpack(cw_buf, iobuf, 2 * slot_bytes, n_codewords); + + /* mode detection and error correction */ + mode = rs16_detect_and_correct(cw_buf, 2 * slot_bytes, n_codewords, epmr, &error_report, bfi, array_of_trust, + ccc_flag, n_pccw, (void *)my_scratch); + + /* for normal slots the maximal number of bit errors is limited */ + test(); +#ifndef APPLY_MAX_ERRORS + IF (sub(slot_bytes, 40) == 0 && mode > 0) + { + IF (sub(error_report & ERROR_REPORT_BEC_MASK, low_br_max_bit_errors_by_mode[mode]) > 0) + { + error_report &= ERROR_REPORT_BEC_MASK; + mode = -1; move16(); + *bfi = 1; move32(); + } + ELSE + { + IF (sub(error_report & ERROR_REPORT_BEC_MASK, low_br_max_bit_errors_by_mode[2]) > 0) + { + error_report &= ~ERROR_REPORT_EP2_OK; + } + IF (sub(error_report & ERROR_REPORT_BEC_MASK, low_br_max_bit_errors_by_mode[3])>0) + { + error_report &= ~ERROR_REPORT_EP3_OK; + } + } + } +#endif + + IF (sub(*bfi, 1) == 0) + { + *data_bytes = 0; move16(); + + Dyn_Mem_Deluxe_Out(); + return error_report; + } + + /* initialization for decoding */ + *data_bytes = fec_get_data_size(mode, ccc_flag, slot_bytes); move32(); + pc_split = fec_get_n_pc(mode, *n_pccw, slot_bytes); + n_crc = get_total_crc_size(slot_bytes, mode, pc_split); + + /* decoding of first code word */ + redundancy_nibbles = sub(hamming_distance_by_mode0[mode], 1); + codeword_length = get_codeword_length(n_codewords, add(slot_bytes, slot_bytes), 0); + + dw_offset = 0; move16(); + cw_offset = 0; move16(); + + FOR (j = redundancy_nibbles; j < codeword_length; j++) + { + cw_buf[dw_offset++] = cw_buf[j]; move16(); + } + cw_offset = add(cw_offset, codeword_length); + + /* decoding of remaining code words */ + redundancy_nibbles = sub(hamming_distance_by_mode1[mode], 1); + + FOR (i = 1; i < n_codewords; i++) + { + codeword_length = get_codeword_length(n_codewords, add(slot_bytes, slot_bytes), i); + + FOR (j = redundancy_nibbles; j < codeword_length; j++) + { + cw_buf[dw_offset++] = cw_buf[j + cw_offset]; move16(); + } + + cw_offset = add(cw_offset, codeword_length); + } + + assert(2 * (*data_bytes + n_crc) == dw_offset && 2 * slot_bytes == cw_offset); + + /* data postproc: hash validation and re-ordering */ + + fec_data_postproc(mode, epmr, iobuf, *data_bytes, cw_buf, slot_bytes, pc_split, bfi); + + IF (sub(*bfi, 1) == 0) + { + *data_bytes = 0; move32(); + error_report &= ERROR_REPORT_BEC_MASK; + Dyn_Mem_Deluxe_Out(); + return error_report; + } + + IF (*bfi == 2) + { + first_bad_cw = 0; move16(); + array_of_trust[*n_pccw] = 0; move16(); + WHILE (array_of_trust[first_bad_cw] != 0) + { + first_bad_cw = add(first_bad_cw, 1); + } + IF (sub(first_bad_cw, *n_pccw) == 0) + { + /* this is the case when CRC failed */ + *be_bp_left = 0; move16(); + } + ELSE + { + *be_bp_left = extract_l(L_mult0(fec_get_n_pc(mode, first_bad_cw, slot_bytes), 4)); move16(); + } + + FOR (i = *n_pccw - 1; i >= 0; i--) + { + if (!array_of_trust[i]) + { + BREAK; + } + } + IF (i < 0) + { + i = sub(*n_pccw, 1); + } + *be_bp_right = sub(extract_l(L_mult0(fec_get_n_pc(mode, i+1, slot_bytes), 4)), 1); move16(); + + } + + IF (ccc_flag == 0) + { + *n_pc = pc_split; move16(); + *m_fec = mode; move16(); + } + + + Dyn_Mem_Deluxe_Out(); + return error_report; +} + +FEC_STATIC void fec_deinterleave_unpack(UWord8 *out, UWord8 *in, Word16 n_nibbles, Word16 n_codewords) +{ + Dyn_Mem_Deluxe_In( + Word16 in_offset, out_offset, codeword_length; + int i, j; + ); + + in_offset = 0; move16(); + out_offset = 0; move16(); + + /* unpack nibbles in input buffer and deinterleave codewords */ + FOR (i = 0; i < n_codewords; i++) + { + codeword_length = get_codeword_length(n_codewords, n_nibbles, i); + FOR (j = 0; j < codeword_length; (j++, out_offset++)) + { + in_offset = add(DEPR_i_mult(j, n_codewords), i); + in_offset = sub(n_nibbles, add(in_offset, 1)); + out[out_offset] = (UWord8)s_and(shr(in[in_offset >> 1], shl(s_and(in_offset, 1), 2)), 15); move16(); + } + } + + assert(out_offset == n_nibbles); + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC Word16 fec_estimate_epmr_from_cw0(UWord8 *cw0, Word8 *t, UWord8 *syndromes, UWord8 *elp, Word8 *deg_elp, + UWord8 *err_pos, UWord8 *err_symb, Word16 n_codewords, Word16 n_symb) +{ + Dyn_Mem_Deluxe_In( + int epmr_lowest_risk_exp; + int start, inc, i, n_candidates; + int first_codeword_length; + int mode_counter; + Word16 epmr; + ); + + epmr_lowest_risk_exp = 0; + first_codeword_length = get_codeword_length(n_codewords, n_symb, 0); + start = 2; + inc = 1; + n_candidates = 0; + + /* test if first code word decodes in mode 0 or 1 without error correction */ + test(); + IF (s_or(syndromes[SYNDROME_IDX(0, 0)], syndromes[SYNDROME_IDX(0, 0) + 1]) == 0 || + s_or(syndromes[SYNDROME_IDX(1, 0)], syndromes[SYNDROME_IDX(1, 0) + 1]) == 0) + { + epmr_lowest_risk_exp = risk_table_f[1][0].exponent; move16(); + } + /* test if first code word decodes in mode 2 or 3 with lower risk */ + IF (sub(deg_elp[DEG_ELP_IDX(2, 0)], t[2]) <= 0) + { + IF (add(risk_table_f[2][deg_elp[DEG_ELP_IDX(2, 0)]].exponent, 8) <= 0) + { + n_candidates++; + start = 2; + } + } + + IF (sub(deg_elp[DEG_ELP_IDX(3, 0)], t[3]) <= 0) + { + IF (add(risk_table_f[3][deg_elp[DEG_ELP_IDX(3, 0)]].exponent, 8) <= 0) + { + n_candidates++; + start = 3; + } + } + + IF (sub(n_candidates, 1) > 0) + { + /* decide on order if mode 2 and 3 are considered */ + IF (simple_float_cmp(risk_table_f[2][deg_elp[DEG_ELP_IDX(2, 0)]], risk_table_f[3][deg_elp[DEG_ELP_IDX(3, 0)]]) < + 0) + { + start = 2; + inc = 1; + } + ELSE + { + start = 3; + inc = -1; + } + } + + FOR ((mode_counter = start, i = 0); i < n_candidates; (mode_counter += inc, i++)) + { + IF (sub(risk_table_f[mode_counter][deg_elp[DEG_ELP_IDX(mode_counter, 0)]].exponent, epmr_lowest_risk_exp) < 0) + { + IF (!rs16_factorize_elp(err_pos + ERR_POS_IDX(mode_counter, 0), elp + ELP_IDX(mode_counter, 0), + deg_elp[DEG_ELP_IDX(mode_counter, 0)], sub(first_codeword_length, 1))) + { + /* code word is decodable with error correction */ + epmr_lowest_risk_exp = risk_table_f[mode_counter][deg_elp[DEG_ELP_IDX(mode_counter, 0)]].exponent; + + rs16_calculate_errors(err_symb + ERR_SYMB_IDX(mode_counter, 0), err_pos + ERR_POS_IDX(mode_counter, 0), + syndromes + SYNDROME_IDX(mode_counter, 0), deg_elp[DEG_ELP_IDX(mode_counter, 0)], + t[mode_counter]); + + FOR (i = 0; i < deg_elp[DEG_ELP_IDX(mode_counter, 0)]; i++) + { + cw0[err_pos[ERR_POS_IDX(mode_counter, 0) + i]] = GF16_ADD( + cw0[err_pos[ERR_POS_IDX(mode_counter, 0) + i]], err_symb[ERR_SYMB_IDX(mode_counter, 0) + i]); + } + BREAK; + } + } + } + + epmr = cw0_get_epmr(cw0, sub(first_codeword_length, 1)); + + IF (add(epmr_lowest_risk_exp, 16) > 0) + { + epmr = add(epmr, 4); move16(); + } + IF (add(epmr_lowest_risk_exp, 8) > 0) + { + epmr = add(epmr, 4); move16(); + } + + Dyn_Mem_Deluxe_Out(); + return epmr; +} + +FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codewords, Word16 *epmr, Word16 *error_report, + int *bfi, UWord8 *array_of_trust, int ccc_flag, Word16 *n_pccw, void *scratch) +{ + Dyn_Mem_Deluxe_In( + UWord8 * syndromes; + UWord8 * elp; + UWord8 * err_pos; + UWord8 * err_symb; + Word8 t[FEC_N_MODES]; + Word8 * deg_elp; + UWord8 * my_scratch; + UWord8 blacklist[FEC_N_MODES]; + UWord8 const *hamming_distance; + + Word16 i, cw_counter, mode_counter, cw_offset; + Word16 codeword_length; + Word16 mode; + Word16 mode_candidates[4]; + Word16 mode_broken[4]; + Word16 error_report_ep_ok[4]; + Word16 n_mode_candidates; + Word16 broken_cw, n_broken_cw; + Word16 j, idx_min; + Word16 n_pccw0; + simple_float val_min_f; + Word16 tmp; + Word16 epmr_position; + simple_float dec_risk_f[FEC_N_MODES]; + simple_float risk_min_f; + simple_float ep_risk_thresh; + + int epmr_dec_fail_increment; + + void (*syndr_calc[3])(UWord8 *, UWord8 *, int); + ); + + /* initialization */ + blacklist[0] = 0; move16(); + blacklist[1] = 0; move16(); + blacklist[2] = 0; move16(); + blacklist[3] = 0; move16(); + mode_broken[0] = 0; move16(); + mode_broken[1] = 0; move16(); + mode_broken[2] = 0; move16(); + mode_broken[3] = 0; move16(); + error_report_ep_ok[0] = ERROR_REPORT_EP1_OK; + error_report_ep_ok[1] = ERROR_REPORT_EP2_OK; + error_report_ep_ok[2] = ERROR_REPORT_EP3_OK; + error_report_ep_ok[3] = ERROR_REPORT_EP4_OK; + my_scratch = (UWord8 *)scratch; + hamming_distance = &hamming_distance_by_mode0[1]; + mode = -1; move16(); + n_mode_candidates = 0; move16(); + risk_min_f.mantissa = SIMPLE_FLOAT_1_MANTISSA; move16(); + risk_min_f.exponent = 0; move16(); + + IF (n_symb <= 80) + { + ep_risk_thresh.mantissa = EP_RISK_THRESH_NS_M; move16(); + ep_risk_thresh.exponent = EP_RISK_THRESH_NS_E; move16(); + } + ELSE + { + ep_risk_thresh.mantissa = EP_RISK_THRESH_OS_M; move16(); + ep_risk_thresh.exponent = EP_RISK_THRESH_OS_E; move16(); + } + + syndr_calc[0] = &rs16_calculate_two_syndromes; + syndr_calc[1] = &rs16_calculate_four_syndromes; + syndr_calc[2] = &rs16_calculate_six_syndromes; + + FOR (i = 0; i < FEC_N_MODES; i++) + { + t[i] = (Word8)shr(sub(hamming_distance[i], 1), 1); move16(); + } + + syndromes = my_scratch; + my_scratch += FEC_TOTAL_SYNDROME_SIZE; + elp = my_scratch; + my_scratch += FEC_TOTAL_ELP_SIZE; + err_pos = my_scratch; + my_scratch += FEC_TOTAL_ERR_POS_SIZE; + err_symb = my_scratch; + my_scratch += FEC_TOTAL_ERROR_SIZE; + deg_elp = (Word8 *)my_scratch; + my_scratch += FEC_TOTAL_DEG_ELP_SIZE; + + *error_report = 0; move16(); + *bfi = 0; move32(); + + /* mode detection (stage 1) */ + codeword_length = get_codeword_length(n_codewords, n_symb, 0); + + epmr_position = sub(codeword_length, 1); + + rs16_calculate_two_syndromes(syndromes + SYNDROME_IDX(0, 0), iobuf, sub(codeword_length, 1)); + + IF (s_or(syndromes[0 + SYNDROME_IDX(0, 0)], syndromes[1 + SYNDROME_IDX(0, 0)]) == 0) + { + + /* data validation for fec mode 1 */ + *epmr = cw0_get_epmr(iobuf, epmr_position); + + dw0_bitswap(iobuf + 2, 1, n_symb / 2); + + IF (!crc1(iobuf + 8, sub(n_symb, 8), *epmr, iobuf + 2, 3, 1)) + { + mode = 0; move16(); + *error_report |= ERROR_REPORT_ALL_OK; + Dyn_Mem_Deluxe_Out(); + return add(mode, 1); + } + ELSE + { + /* reverse bit swap */ + dw0_bitswap(iobuf + 2, 1, n_symb / 2); + + *epmr = add(*epmr, 4); move16(); + } + } + + blacklist[0] = 1; move16(); + + /* mode detection (stage 2) */ + + /* calculate syndromes of code words 0 to 5 and modes 1 to 3 */ + cw_offset = 0; move16(); + + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); + + rs16_calculate_six_syndromes(syndromes + SYNDROME_IDX(1, cw_counter), iobuf + cw_offset, + sub(codeword_length, 1)); + + cw_offset = add(cw_offset, codeword_length); + + FOR (mode_counter = FEC_N_MODES - 1; mode_counter >= 1; mode_counter--) + { + FOR (i = 0; i < sub(hamming_distance[mode_counter], 1); i++) + { + syndromes[SYNDROME_IDX(mode_counter, cw_counter) + i] = GF16_ADD( + syndromes[SYNDROME_IDX(1, cw_counter) + i], sig_poly_syndr[mode_counter][i]); move16(); + } + } + } + + /* check for valid code words */ + FOR (mode_counter = 1; mode_counter < FEC_N_MODES; mode_counter++) + { + n_broken_cw = 0; + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + broken_cw = 0; + FOR (i = 0; i < sub(hamming_distance[mode_counter], 1); i++) + { + broken_cw = s_or(broken_cw, syndromes[SYNDROME_IDX(mode_counter, cw_counter) + i]); move16(); + } + IF (broken_cw != 0) + { + n_broken_cw = add(n_broken_cw, 1); + } + } + + IF (n_broken_cw == 0) + { + mode = mode_counter; move16(); + cw_offset = 0; move16(); + + *epmr = cw0_get_epmr(iobuf, epmr_position); + + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); + FOR (i = 0; i <= EP_SIG_POLY_DEG; i++) + { + iobuf[cw_offset + i] = GF16_ADD(iobuf[cw_offset + i], sig_polys[mode][i]); + } + cw_offset = add(cw_offset, codeword_length); + } + } + } + + IF (mode < 0) /* mode hasn't been detected so far -> errors occurred in transmission */ + { + /* calculate error locator polynomials for code words 0 to 5 */ + FOR (mode_counter = 1; mode_counter < FEC_N_MODES; mode_counter++) + { + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + deg_elp[DEG_ELP_IDX(mode_counter, cw_counter)] = rs16_calculate_elp( + elp + ELP_IDX(mode_counter, cw_counter), syndromes + SYNDROME_IDX(mode_counter, cw_counter), + t[mode_counter]); move16(); + IF (sub(deg_elp[DEG_ELP_IDX(mode_counter, cw_counter)], t[mode_counter]) > 0) + { + blacklist[mode_counter] = 1; move16(); + BREAK; + } + } + } + + /* risk analysis for mode candidate selection */ + FOR (mode_counter = 1; mode_counter < FEC_N_MODES; mode_counter++) + { + dec_risk_f[mode_counter].mantissa = SIMPLE_FLOAT_1_MANTISSA; move16(); + dec_risk_f[mode_counter].exponent = 0; move16(); + + IF (blacklist[mode_counter] == 0) + { + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + dec_risk_f[mode_counter] = simple_float_mul( + dec_risk_f[mode_counter], + risk_table_f[mode_counter][deg_elp[DEG_ELP_IDX(mode_counter, cw_counter)]]); move16(); + } + + IF (simple_float_cmp(dec_risk_f[mode_counter], ep_risk_thresh) <= 0) + { + mode_candidates[n_mode_candidates++] = mode_counter; move16(); + } + + IF (simple_float_cmp(dec_risk_f[mode_counter], risk_min_f) < 0) + { + risk_min_f = dec_risk_f[mode_counter]; move16(); + } + } + } + assert(n_mode_candidates <= 4); // suppress false gcc warning when OPTIM=3 + + /* sort mode candidates by risk */ + FOR (i = 0; i < n_mode_candidates; i++) + { + idx_min = i; move16(); + val_min_f = dec_risk_f[mode_candidates[i]]; move16(); + + FOR (j = i + 1; j < n_mode_candidates; j++) + { + IF (simple_float_cmp(dec_risk_f[mode_candidates[j]], val_min_f) < 0) + { + val_min_f = dec_risk_f[mode_candidates[j]]; move16(); + idx_min = j; move16(); + } + } + + IF (sub(idx_min, i) > 0) + { + tmp = mode_candidates[i]; move16(); + mode_candidates[i] = mode_candidates[idx_min]; move16(); + mode_candidates[idx_min] = tmp; move16(); + } + } + + /* try out candidate modes */ + FOR (i = 0; i < n_mode_candidates; i++) + { + mode = mode_candidates[i]; move16(); + + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); + + IF (deg_elp[DEG_ELP_IDX(mode, cw_counter)]) + { + IF (rs16_factorize_elp(err_pos + ERR_POS_IDX(mode, cw_counter), elp + ELP_IDX(mode, cw_counter), + deg_elp[DEG_ELP_IDX(mode, cw_counter)], sub(codeword_length, 1))) + { + /* elp did not split into distinct linear factors or error position was out of range */ + mode = -1; move16(); + BREAK; + } + } + } + IF (mode > 0) + { + /* decodable mode with lowest risk has been found */ + BREAK; + } + } + + IF (mode < 0) + { + /* no decodable mode has been found */ + *error_report = ERROR_REPORT_BEC_MASK; move16(); + *bfi = 1; move32(); + mode = -1; move16(); + + *epmr = fec_estimate_epmr_from_cw0(iobuf, t, syndromes, elp, deg_elp, err_pos, err_symb, n_codewords, + n_symb); + + Dyn_Mem_Deluxe_Out(); + return mode; + } + + /* perform error correction */ + cw_offset = 0; move16(); + *error_report = 0; move16(); + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) + { + codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); + + IF (deg_elp[DEG_ELP_IDX(mode, cw_counter)]) + { + rs16_calculate_errors( + err_symb + ERR_SYMB_IDX(mode, cw_counter), err_pos + ERR_POS_IDX(mode, cw_counter), + syndromes + SYNDROME_IDX(mode, cw_counter), deg_elp[DEG_ELP_IDX(mode, cw_counter)], t[mode]); + + /* correct errors and sum up number of corrected bits */ + FOR (i = 0; i < deg_elp[DEG_ELP_IDX(mode, cw_counter)]; i++) + { + iobuf[err_pos[ERR_POS_IDX(mode, cw_counter) + i] + cw_offset] = + GF16_ADD(iobuf[err_pos[ERR_POS_IDX(mode, cw_counter) + i] + cw_offset], + err_symb[ERR_SYMB_IDX(mode, cw_counter) + i]); + *error_report = add(*error_report, + rs16_bit_count_table[err_symb[ERR_SYMB_IDX(mode, cw_counter) + i]]); move16(); + } + + FOR (i = 0; i < mode; i ++) + { + IF(deg_elp[DEG_ELP_IDX(mode, cw_counter)] > i) + { + mode_broken[i] = 1; + } + } + } + + FOR (i = 0; i <= EP_SIG_POLY_DEG; i++) + { + iobuf[cw_offset + i] = GF16_ADD(iobuf[cw_offset + i], sig_polys[mode][i]); + } + cw_offset = add(cw_offset, codeword_length); + } + + /* set epmr according to risk value of cw0 */ + epmr_dec_fail_increment = 8; + + IF (add(risk_table_f[mode][deg_elp[DEG_ELP_IDX(mode, 0)]].exponent, 8) <= 0) + { + epmr_dec_fail_increment = sub(epmr_dec_fail_increment, 4); + } + IF (add(risk_table_f[mode][deg_elp[DEG_ELP_IDX(mode, 0)]].exponent, 16) <= 0) + { + epmr_dec_fail_increment = sub(epmr_dec_fail_increment, 4); + } + + *epmr = cw0_get_epmr(iobuf, epmr_position) + epmr_dec_fail_increment; + } + + /* mode has been successfully detected -> now check and try to correct remaining code words*/ + *n_pccw = fec_get_n_pccw(n_symb / 2, mode + 1, ccc_flag); + IF (ccc_flag == 0) + { + n_pccw0 = fec_get_n_pccw(n_symb / 2, mode + 1, ccc_flag); + *n_pccw = n_pccw0; + } + ELSE + { + n_pccw0 = 0; + } + + FOR (cw_counter = 6; cw_counter < n_codewords; cw_counter++) + { + /* usual error correction scheme: syndromes -> elp's, errors, etc. */ + codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); + array_of_trust[n_codewords - 1 - cw_counter] = 1; move16(); + + syndr_calc[sub(t[mode], 1)](syndromes, iobuf + cw_offset, sub(codeword_length, 1)); + + deg_elp[0] = rs16_calculate_elp(elp, syndromes, t[mode]); move16(); + + FOR (i = 0; i < mode; i ++) + { + IF(deg_elp[0] > i) + { + mode_broken[i] = 1; + } + } + IF (sub(deg_elp[0], t[mode]) > 0) + { + FOR (i = 0; i < 4; i ++) + { + mode_broken[i] = 1; + } + cw_offset = add(cw_offset, codeword_length); + IF (cw_counter < n_codewords - n_pccw0) + { + *error_report = ERROR_REPORT_BEC_MASK; move16(); + mode = -1; move16(); + *bfi = 1; move32(); + + BREAK; + } + ELSE + { + *bfi = 2; move32(); + array_of_trust[n_codewords - 1 - cw_counter] = 0; move16(); + CONTINUE; + } + } + + IF (deg_elp[0]) + { + IF (rs16_factorize_elp(err_pos, elp, deg_elp[0], sub(codeword_length, 1))) + { + cw_offset = add(cw_offset, codeword_length); + FOR (i = 0; i < 4; i ++) + { + mode_broken[i] = 1; + } + IF (add(n_pccw0, sub(cw_counter, n_codewords)) < 0) + { + *error_report = ERROR_REPORT_BEC_MASK; move16(); + mode = -1; move16(); + *bfi = 1; move32(); + + BREAK; + } + ELSE + { + *bfi = 2; move32(); + array_of_trust[n_codewords - 1 - cw_counter] = 0; move16(); + CONTINUE; + } + } + + rs16_calculate_errors(err_symb, err_pos, syndromes, deg_elp[0], t[mode]); + + /* correct errors and sum up number of corrected bits */ + FOR (i = 0; i < deg_elp[0]; i++) + { + iobuf[err_pos[i] + cw_offset] = GF16_ADD(iobuf[err_pos[i] + cw_offset], err_symb[i]); + *error_report = add(*error_report, rs16_bit_count_table[err_symb[i]]); + } + } + cw_offset = add(cw_offset, codeword_length); + if (add(risk_table_f[mode][deg_elp[0]].exponent, 16) > 0) + { + array_of_trust[n_codewords - 1 - cw_counter] = 0; move16(); + } + } + + *error_report &= ERROR_REPORT_BEC_MASK; + FOR (i = 0; i < 4; i ++) + { + IF (!mode_broken[i]) + { + *error_report |= error_report_ep_ok[i]; + } + } + + Dyn_Mem_Deluxe_Out(); + IF (mode >= 0) + { + return add(mode, 1); + } + + return -1; +} + +FEC_STATIC void rs16_calculate_six_syndromes(UWord8 *syndromes, UWord8 *cw, int cw_poly_deg) +{ + Dyn_Mem_Deluxe_In( + int i; + UWord8 buffer[15]; + ); + + assert(cw_poly_deg >= 12); + + FOR (i = 0; i <= cw_poly_deg; i++) + { + buffer[i] = cw[i]; move16(); + } + + syndromes[0] = buffer[0]; move16(); + syndromes[1] = buffer[0]; move16(); + syndromes[2] = buffer[0]; move16(); + syndromes[3] = buffer[0]; move16(); + syndromes[4] = buffer[0]; move16(); + syndromes[5] = buffer[0]; move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[1], 32)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[1], 64)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[1], 128)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[1], 48)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[1], 96)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[1], 192)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[2], 64)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[2], 48)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[2], 192)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[2], 80)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[2], 112)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[2], 240)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[3], 128)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[3], 192)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[3], 160)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[3], 240)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[3], 16)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[3], 128)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[4], 48)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[4], 80)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[4], 240)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[4], 32)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[4], 96)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[4], 160)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[5], 96)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[5], 112)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[5], 16)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[5], 96)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[5], 112)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[5], 16)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[6], 192)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[6], 240)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[6], 128)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[6], 160)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[6], 16)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[6], 192)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[7], 176)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[7], 144)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[7], 192)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[7], 208)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[7], 96)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[7], 240)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[8], 80)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[8], 32)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[8], 160)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[8], 64)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[8], 112)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[8], 128)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[9], 160)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[9], 128)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[9], 240)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[9], 192)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[9], 16)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[9], 160)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[10], 112)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[10], 96)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[10], 16)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[10], 112)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[10], 96)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[10], 16)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[11], 224)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[11], 176)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[11], 128)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[11], 144)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[11], 112)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[11], 192)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[12], 240)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[12], 160)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[12], 192)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[12], 128)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[12], 16)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[12], 240)); move16(); + + IF (sub(cw_poly_deg, 13) >= 0) + { + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[13], 208)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[13], 224)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[13], 160)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[13], 176)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[13], 96)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[13], 128)); move16(); + } + + IF (sub(cw_poly_deg, 14) >= 0) + { + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[14], 144)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[14], 208)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[14], 240)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[14], 224)); move16(); + syndromes[4] = GF16_ADD(syndromes[4], GF16_MUL0(buffer[14], 112)); move16(); + syndromes[5] = GF16_ADD(syndromes[5], GF16_MUL0(buffer[14], 160)); move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC void rs16_calculate_four_syndromes(UWord8 *syndromes, UWord8 *cw, int cw_poly_deg) +{ + Dyn_Mem_Deluxe_In( + int i; + UWord8 buffer[15]; + ); + + assert(cw_poly_deg >= 12); + + FOR (i = 0; i <= cw_poly_deg; i++) + { + buffer[i] = cw[i]; move16(); + } + + syndromes[0] = buffer[0]; move16(); + syndromes[1] = buffer[0]; move16(); + syndromes[2] = buffer[0]; move16(); + syndromes[3] = buffer[0]; move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[1], 32)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[1], 64)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[1], 128)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[1], 48)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[2], 64)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[2], 48)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[2], 192)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[2], 80)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[3], 128)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[3], 192)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[3], 160)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[3], 240)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[4], 48)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[4], 80)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[4], 240)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[4], 32)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[5], 96)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[5], 112)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[5], 16)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[5], 96)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[6], 192)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[6], 240)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[6], 128)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[6], 160)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[7], 176)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[7], 144)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[7], 192)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[7], 208)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[8], 80)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[8], 32)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[8], 160)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[8], 64)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[9], 160)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[9], 128)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[9], 240)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[9], 192)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[10], 112)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[10], 96)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[10], 16)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[10], 112)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[11], 224)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[11], 176)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[11], 128)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[11], 144)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[12], 240)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[12], 160)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[12], 192)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[12], 128)); move16(); + + IF (sub(cw_poly_deg, 13) >= 0) + { + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[13], 208)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[13], 224)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[13], 160)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[13], 176)); move16(); + } + + IF (sub(cw_poly_deg, 14) >= 0) + { + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[14], 144)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[14], 208)); move16(); + syndromes[2] = GF16_ADD(syndromes[2], GF16_MUL0(buffer[14], 240)); move16(); + syndromes[3] = GF16_ADD(syndromes[3], GF16_MUL0(buffer[14], 224)); move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC void rs16_calculate_two_syndromes(UWord8 *syndromes, UWord8 *cw, int cw_poly_deg) +{ + Dyn_Mem_Deluxe_In( + int i; + UWord8 buffer[15]; + ); + + assert(cw_poly_deg >= 12); + + FOR (i = 0; i <= cw_poly_deg; i++) + { + buffer[i] = cw[i]; move16(); + } + + syndromes[0] = buffer[0]; move16(); + syndromes[1] = buffer[0]; move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[1], 32)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[1], 64)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[2], 64)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[2], 48)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[3], 128)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[3], 192)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[4], 48)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[4], 80)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[5], 96)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[5], 112)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[6], 192)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[6], 240)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[7], 176)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[7], 144)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[8], 80)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[8], 32)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[9], 160)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[9], 128)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[10], 112)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[10], 96)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[11], 224)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[11], 176)); move16(); + + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[12], 240)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[12], 160)); move16(); + + IF (sub(cw_poly_deg, 13) >= 0) + { + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[13], 208)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[13], 224)); move16(); + } + + IF (sub(cw_poly_deg, 14) >= 0) + { + syndromes[0] = GF16_ADD(syndromes[0], GF16_MUL0(buffer[14], 144)); move16(); + syndromes[1] = GF16_ADD(syndromes[1], GF16_MUL0(buffer[14], 208)); move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +FEC_STATIC Word8 rs16_calculate_elp(UWord8 *elp, UWord8 *syndromes, Word16 t) +/* calculates error locator polynomial vie Petterson's algorithm */ +{ + Dyn_Mem_Deluxe_In( + Word8 ret; + UWord8 det, det_inv, aux, all_s, *s; + UWord8 s22, s33, s44, s13, s14, s15; + UWord8 s23, s24, s25, s34, s35; + UWord8 a, b, c, d, e, f; + ); + + ret = 0; move16(); + all_s = 0; move16(); + s = syndromes; move16(); + elp[0] = 1; move16(); + basop_memset(elp + 1, 0, 3); + + SWITCH (t) + { + case 3: + { + /* check for errors */ + all_s = (UWord8)s_or(s[0], s_or(s[1], s_or(s[2], s_or(s[3], s_or(s[4], s[5]))))); + + IF (all_s == 0) + { + BREAK; + } + + /* assume 3 errors */ + s22 = GF16_MUL(s[1], s[1]); + s33 = GF16_MUL(s[2], s[2]); + s44 = GF16_MUL(s[3], s[3]); + s13 = GF16_MUL(s[0], s[2]); + + det = GF16_ADD(GF16_ADD(GF16_MUL(s13, s[4]), GF16_MUL(s44, s[0])), + GF16_ADD(GF16_MUL(s22, s[4]), GF16_MUL(s33, s[2]))); + + IF (det) + { + det_inv = (UWord8)shl(gf16_inv_table[det], 4); + + s14 = GF16_MUL(s[0], s[3]); + s15 = GF16_MUL(s[0], s[4]); + + s23 = GF16_MUL(s[1], s[2]); + s24 = GF16_MUL(s[1], s[3]); + s25 = GF16_MUL(s[1], s[4]); + + s34 = GF16_MUL(s[2], s[3]); + s35 = GF16_MUL(s[2], s[4]); + + a = GF16_ADD(s35, s44) << 4; + b = GF16_ADD(s15, s33) << 4; + c = GF16_ADD(s13, s22) << 4; + d = GF16_ADD(s34, s25) << 4; + e = GF16_ADD(s23, s14) << 4; + f = GF16_ADD(s24, s33) << 4; + + aux = GF16_ADD(GF16_ADD(GF16_MUL0(a, s[3]), GF16_MUL0(d, s[4])), GF16_MUL0(f, s[5])); + elp[3] = GF16_MUL0(aux, det_inv); + + aux = GF16_ADD(GF16_ADD(GF16_MUL0(d, s[3]), GF16_MUL0(b, s[4])), GF16_MUL0(e, s[5])); + elp[2] = GF16_MUL0(aux, det_inv); + + aux = GF16_ADD(GF16_ADD(GF16_MUL0(f, s[3]), GF16_MUL0(e, s[4])), GF16_MUL0(c, s[5])); + elp[1] = GF16_MUL0(aux, det_inv); + + IF (elp[3] == 0) + { + ret = (Word8) add(t, 1); + } + ELSE + { + ret = 3; move16(); + } + BREAK; + } + + /* assume two errors */ + det = GF16_ADD(GF16_MUL(syndromes[0], syndromes[2]), GF16_MUL(syndromes[1], syndromes[1])); + + IF (det) + { + det_inv = (UWord8)shl(gf16_inv_table[det], 4); + + aux = GF16_ADD(GF16_MUL(syndromes[1], syndromes[2]), GF16_MUL(syndromes[0], syndromes[3])); + elp[1] = GF16_MUL0(aux, det_inv); + + aux = GF16_ADD(GF16_MUL(syndromes[2], syndromes[2]), GF16_MUL(syndromes[1], syndromes[3])); + elp[2] = GF16_MUL0(aux, det_inv); + + /* check remaining LSF relations */ + aux = (UWord8)s_or(GF16_ADD(GF16_ADD(GF16_MUL(elp[2], s[2]), GF16_MUL(elp[1], s[3])), s[4]), + GF16_ADD(GF16_ADD(GF16_MUL(elp[2], s[3]), GF16_MUL(elp[1], s[4])), s[5])); + + aux = (UWord8)s_or(aux, elp[2] == 0); + + IF (aux != 0) + { + ret = (Word8) add(t, 1); + } + ELSE + { + ret = 2; move16(); + } + BREAK; + } + + /* assume one error */ + IF (syndromes[0] != 0) + { + elp[1] = GF16_MUL(syndromes[1], gf16_inv_table[syndromes[0]]); + + /* check remaining LSF relations */ + aux = (UWord8)s_or(s_or(GF16_ADD(GF16_MUL(elp[1], s[1]), s[2]), GF16_ADD(GF16_MUL(elp[1], s[2]), s[3])), + s_or(GF16_ADD(GF16_MUL(elp[1], s[3]), s[4]), GF16_ADD(GF16_MUL(elp[1], s[4]), s[5]))); + + aux = (UWord8)s_or(aux, elp[1] == 0); + + IF (aux != 0) + { + ret = (Word8) add(t, 1); + } + ELSE + { + ret = 1; move16(); + } + BREAK; + } + + ret = (Word8) add(t, 1); + BREAK; + } + case 2: + { + all_s = (UWord8)s_or(s[0], s_or(s[1], s_or(s[2], s[3]))); + + IF (all_s == 0) + { + BREAK; + } + + /* assume two errors */ + det = GF16_ADD(GF16_MUL(syndromes[0], syndromes[2]), GF16_MUL(syndromes[1], syndromes[1])); + + IF (det) + { + det_inv = (UWord8)shl(gf16_inv_table[det], 4); + + aux = GF16_ADD(GF16_MUL(syndromes[1], syndromes[2]), GF16_MUL(syndromes[0], syndromes[3])); + elp[1] = GF16_MUL0(aux, det_inv); + + aux = GF16_ADD(GF16_MUL(syndromes[2], syndromes[2]), GF16_MUL(syndromes[1], syndromes[3])); + elp[2] = GF16_MUL0(aux, det_inv); + + IF (elp[2] == 0) + { + ret = (Word8) add(t, 1); + } + ELSE + { + ret = 2; move16(); + } + BREAK; + } + + /* assume one error */ + IF (syndromes[0] != 0) + { + elp[1] = GF16_MUL(syndromes[1], gf16_inv_table[syndromes[0]]); + + /* check remaining LSF relation */ + aux = (UWord8)s_or(GF16_ADD(GF16_MUL(elp[1], s[1]), s[2]), GF16_ADD(GF16_MUL(elp[1], s[2]), s[3])); + aux = (UWord8)s_or(aux, elp[1] == 0); + IF (aux != 0) + { + ret = (Word8) add(t, 1); + } + ELSE + { + ret = 1; move16(); + } + BREAK; + } + + ret = (Word8) add(t, 1); + BREAK; + } + case 1: + { + all_s = (UWord8)s_or(s[0], s[1]); + + IF (all_s == 0) + { + BREAK; + } + + IF (syndromes[0] != 0) + { + elp[1] = GF16_MUL(syndromes[1], gf16_inv_table[syndromes[0]]); + IF (elp[1] == 0) + { + ret = (Word8) add(t, 1); + } + ELSE + { + ret = 1; move16(); + } + BREAK; + } + + ret = (Word8) add(t, 1); + BREAK; + } + default: assert(0 && "calculating elp of this degree not implemented"); + } + + Dyn_Mem_Deluxe_Out(); + return ret; +} + +FEC_STATIC Word16 rs16_factorize_elp(UWord8 *err_pos, UWord8 *elp, Word16 deg_elp, Word16 max_pos) +{ + Dyn_Mem_Deluxe_In( + UWord8 beta, gamma; + Word16 zeros, err_pos0, err_pos1, err_pos2, ret; + ); + + beta = 0; move16(); + gamma = 0; move16(); + zeros = 0; move16(); + ret = 0; move16(); + + SWITCH (deg_elp) + { + case 0: BREAK; + + case 1: + err_pos0 = gf16_log_g[elp[1]]; move16(); + IF (sub(err_pos0, max_pos) > 0) + { + ret = 1; move16(); + BREAK; + } + + err_pos[0] = (UWord8)err_pos0; move16(); + BREAK; + + case 2: + zeros = rs16_elp_deg2_table[s_or(elp[1], shl(elp[2], 4))]; move16(); + IF (zeros == 0) + { + Dyn_Mem_Deluxe_Out(); + return 1; + } + + err_pos0 = s_and(zeros, 15); + err_pos1 = s_and(shr(zeros, 4), 15); + + IF (sub(err_pos0, max_pos) > 0 || sub(err_pos1, max_pos) > 0) + { + ret = 1; move16(); + BREAK; + } + + err_pos[0] = (UWord8)err_pos0; move16(); + err_pos[1] = (UWord8)err_pos1; move16(); + BREAK; + + case 3: + /* beta = a*a + b, gamma = a*b + c */ + beta = GF16_ADD(GF16_MUL(elp[1], elp[1]), elp[2]); + gamma = GF16_ADD(GF16_MUL(elp[1], elp[2]), elp[3]); + zeros = rs16_elp_deg3_table[beta | gamma << 4]; + + IF (zeros == 0) + /* elp does not split over GF(16) or has multiple zeros */ + { + ret = 1; move16(); + BREAK; + } + + /* remove shift from zeros */ + err_pos0 = GF16_ADD(s_and(zeros, 15), elp[1]); + err_pos1 = GF16_ADD(s_and(shr(zeros, 4), 15), elp[1]); + err_pos2 = GF16_ADD(s_and(shr(zeros, 8), 15), elp[1]); + + IF (err_pos0 == 0 || err_pos1 == 0 || err_pos2 == 0) + { + test(); test(); + Dyn_Mem_Deluxe_Out(); + return 1; + } + + err_pos0 = gf16_log_g[err_pos0]; + err_pos1 = gf16_log_g[err_pos1]; + err_pos2 = gf16_log_g[err_pos2]; + + IF (sub(err_pos0, max_pos) > 0 || sub(err_pos1, max_pos) > 0 || sub(err_pos2, max_pos) > 0) + { + test(); test(); + ret = 1; move16(); + BREAK; + } + + err_pos[0] = (UWord8)err_pos0; move16(); + err_pos[1] = (UWord8)err_pos1; move16(); + err_pos[2] = (UWord8)err_pos2; move16(); + + BREAK; + + default: assert(0 && "invalid degree in rs16_error_locator"); + } + + Dyn_Mem_Deluxe_Out(); + return ret; +} + +FEC_STATIC void rs16_calculate_errors(UWord8 *err_symb, UWord8 *err_pos, UWord8 *syndromes, Word8 deg_elp, Word8 t) +{ + Dyn_Mem_Deluxe_In( + UWord8 det_inv; + UWord8 x0, x1, x2; + UWord8 x0sq, x1sq, x2sq; + UWord8 c0, c1, c2; + UWord8 s0, s1, s2; + UWord8 tmp; + ); + + assert(deg_elp <= t); + UNUSED(t); + + SWITCH (deg_elp) + { + case 0: BREAK; + + case 1: + err_symb[0] = GF16_MUL(gf16_g_pow[15 - err_pos[0]], syndromes[0]); move16(); + + BREAK; + + case 2: + s0 = (UWord8)shl(syndromes[0], 4); + s1 = (UWord8)shl(syndromes[1], 4); + + x0 = gf16_g_pow[err_pos[0]]; move16(); + x1 = gf16_g_pow[err_pos[1]]; move16(); + + x0sq = GF16_MUL(x0, x0); + x1sq = GF16_MUL(x1, x1); + + tmp = GF16_ADD(GF16_MUL(x0sq, x1), GF16_MUL(x1sq, x0)); + det_inv = (UWord8)shl(gf16_inv_table[tmp], 4); + + tmp = GF16_ADD(GF16_MUL0(x1sq, s0), GF16_MUL0(x1, s1)); + err_symb[0] = GF16_MUL0(tmp, det_inv); move16(); + + tmp = GF16_ADD(GF16_MUL0(x0sq, s0), GF16_MUL0(x0, s1)); + err_symb[1] = GF16_MUL0(tmp, det_inv); move16(); + + BREAK; + + case 3: + s0 = (UWord8)shl(syndromes[0], 4); + s1 = (UWord8)shl(syndromes[1], 4); + s2 = (UWord8)shl(syndromes[2], 4); + + x0 = gf16_g_pow[err_pos[0]]; move16(); + x1 = gf16_g_pow[err_pos[1]]; move16(); + x2 = gf16_g_pow[err_pos[2]]; move16(); + + x0sq = GF16_MUL(x0, x0); + x1sq = GF16_MUL(x1, x1); + x2sq = GF16_MUL(x2, x2); + + tmp = GF16_MUL(GF16_ADD(x1, x0), GF16_ADD(x2, x0)); + tmp = GF16_MUL(GF16_ADD(x2, x1), tmp); + det_inv = (UWord8)shl(gf16_inv_table[tmp], 4); + + c0 = GF16_ADD(GF16_MUL(x1, x2sq), GF16_MUL(x2, x1sq)); + c1 = GF16_ADD(x2sq, x1sq); + c2 = GF16_ADD(x2, x1); + + err_symb[0] = GF16_ADD(GF16_ADD(GF16_MUL0(c0, s0), GF16_MUL0(c1, s1)), GF16_MUL0(c2, s2)); move16(); + + c0 = GF16_ADD(GF16_MUL(x0, x2sq), GF16_MUL(x2, x0sq)); + c1 = GF16_ADD(x2sq, x0sq); + c2 = GF16_ADD(x2, x0); + + err_symb[1] = GF16_ADD(GF16_ADD(GF16_MUL0(c0, s0), GF16_MUL0(c1, s1)), GF16_MUL0(c2, s2)); move16(); + + c0 = GF16_ADD(GF16_MUL(x0, x1sq), GF16_MUL(x1, x0sq)); + c1 = GF16_ADD(x1sq, x0sq); + c2 = GF16_ADD(x1, x0); + + err_symb[2] = GF16_ADD(GF16_ADD(GF16_MUL0(c0, s0), GF16_MUL0(c1, s1)), GF16_MUL0(c2, s2)); move16(); + + tmp = GF16_MUL0(err_symb[0], det_inv); + err_symb[0] = GF16_MUL(tmp, gf16_inv_table[x0]); move16(); + + tmp = GF16_MUL0(err_symb[1], det_inv); + err_symb[1] = GF16_MUL(tmp, gf16_inv_table[x1]); move16(); + + tmp = GF16_MUL0(err_symb[2], det_inv); + err_symb[2] = GF16_MUL(tmp, gf16_inv_table[x2]); move16(); + + BREAK; + + default: assert(0 && "method not implemented\n"); BREAK; + } + + Dyn_Mem_Deluxe_Out(); +} + +/* hash functions for data validation */ + +/* hamming distance 4 */ +static const UWord32 crc14_mask[16] = {0, 17989, 35978, 51919, 71956, 89937, 103838, 119771, + 143912, 160877, 179874, 194791, 207676, 224633, 239542, 254451}; + +/* hamming distance 4 */ +static const UWord32 crc22_mask[16] = {0, 4788009, 9576018, 14356859, 19152036, 23933837, 28713718, 33500639, + 33650273, 38304072, 43214899, 47867674, 52775621, 57427436, 62346391, 67001278}; + +FEC_STATIC Word16 crc1(UWord8 *data, Word16 data_size, Word16 epmr, UWord8 *hash, Word16 hash_size, Word16 check) +{ + Dyn_Mem_Deluxe_In( + UWord32 const *mask; + int shift, i, fail; + UWord32 rem; + ); + + fail = 0; move16(); + rem = 0; move16(); + + assert(hash_size > 0); + + SWITCH (hash_size) + { + case 2: + shift = 14; move16(); + mask = crc14_mask; move32(); + BREAK; + case 3: + shift = 22; move16(); + mask = crc22_mask; move32(); + BREAK; + default: + shift = 0; + mask = 0; + assert(0 && "crc hash size not implemented"); + } + + /* data array contains 4-bit words */ + FOR (i = data_size - 1; i >= 0; i--) + { + rem = UL_xor(UL_lshl(rem, 4), data[i]); move32(); + rem = UL_xor(rem, mask[UL_and(UL_lshr(rem, shift), 15)]); move32(); + } + + rem = UL_xor(UL_lshl(rem, 4), UL_lshl(epmr, 2)); + rem = UL_xor(rem, mask[UL_and(UL_lshr(rem, shift), 15)]); move32(); + + FOR (i = 0; i < 2 * hash_size - 1; i++) + { + rem = UL_lshl(rem, 4); + rem = UL_xor(rem, mask[UL_and(UL_lshr(rem, shift), 15)]); move32(); + } + + rem = UL_xor(rem, UL_lshl((UWord32)epmr, shift)); move32(); + + IF (check) + { + /* test hash value */ + FOR (i = 0; i < 2 * hash_size; i++) + { + fail = s_or(fail, UL_xor(hash[i], UL_and(UL_lshr(rem, shl(i, 2)), 15))); move32(); + } + } + ELSE + { + /* write hash value */ + for (i = 0; i < 2 * hash_size; i++) + { + hash[i] = (UWord8)UL_and(UL_lshr(rem, shl(i, 2)), 15); move32(); + } + } + + Dyn_Mem_Deluxe_Out(); + return fail; +} + +/* hamming distance = 4 */ +static const UWord32 crc16_mask[16] = {0, 107243, 190269, 214486, 289937, 380538, 428972, 469319, + 579874, 621513, 671263, 761076, 832947, 857944, 938638, 1044581}; + +FEC_STATIC Word16 crc2(UWord8 *data, Word16 data_size, UWord8 *hash, Word16 hash_size, Word16 check) +{ + Dyn_Mem_Deluxe_In( + UWord32 const *mask; + int shift, i, fail; + UWord32 rem; + ); + + fail = 0; move16(); + rem = 0; move16(); + + assert(hash_size > 0); + + SWITCH (hash_size) + { + case 2: + shift = 16; move16(); + mask = crc16_mask; move32(); + BREAK; + default: + shift = 0; + mask = 0; + assert(0 && "crc hash size not implemented"); + } + + /* data array contains 4-bit words */ + FOR (i = data_size - 1; i >= 0; i--) + { + rem = UL_xor(UL_lshl(rem, 4), data[i]); move32(); + rem = UL_xor(rem, mask[UL_and(UL_lshr(rem, shift), 15)]); move32(); + } + + FOR (i = 0; i < 2 * hash_size; i++) + { + rem = UL_lshl(rem, 4); + rem = UL_xor(rem, mask[UL_and(UL_lshr(rem, shift), 15)]); move32(); + } + + IF (check) + { + /* test hash value */ + FOR (i = 0; i < 2 * hash_size; i++) + { + fail = s_or(fail, UL_xor(hash[i], UL_and(UL_lshr(rem, shl(i, 2)), 15))); move32(); + } + } + ELSE + { + /* write hash value */ + FOR (i = 0; i < 2 * hash_size; i++) + { + hash[i] = (UWord8)UL_and(UL_lshr(rem, shl(i, 2)), 15); move32(); + } + } + + Dyn_Mem_Deluxe_Out(); + return fail; +} + +/* simple float implementation */ + +FEC_STATIC simple_float simple_float_mul(simple_float op1, simple_float op2) +{ + Dyn_Mem_Deluxe_In( + simple_float rop; + Word32 aux; + ); + aux = L_shr(L_mult0(op1.mantissa, op2.mantissa), 14); + rop.exponent = add(op1.exponent, op2.exponent); + IF (L_and(aux, 32768L)) + { + aux = L_shr(aux, 1); + rop.exponent = add(rop.exponent, 1); + } + rop.mantissa = extract_l(aux); + Dyn_Mem_Deluxe_Out(); + return rop; +} + +/* Auxiliary */ + +FEC_STATIC Word16 simple_float_cmp(simple_float op1, simple_float op2) +/* returns 1 if op1 > op2, 0 if op1 = op2, and -1 if op1 < op2 */ +{ + Dyn_Mem_Deluxe_In( + Word16 rval; + Word16 mdiff; + Word16 ediff; + ); + + rval = 0; move16(); + + ediff = sub(op1.exponent, op2.exponent); + mdiff = sub(op1.mantissa, op2.mantissa); + + IF (ediff == 0) + { + if (mdiff > 0) + { + rval = 1; + } + if (mdiff < 0) + { + rval = -1; + } + } + ELSE + { + if (ediff > 0) + { + rval = 1; + } + if (ediff < 0) + { + rval = -1; + } + } + + Dyn_Mem_Deluxe_Out(); + return rval; +} + + diff --git a/lib_lc3plus/apply_global_gain_fx.c b/lib_lc3plus/apply_global_gain_fx.c new file mode 100644 index 000000000..7c5220f10 --- /dev/null +++ b/lib_lc3plus/apply_global_gain_fx.c @@ -0,0 +1,66 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 global_gain_idx, Word16 global_gain_off) +{ + Counter i; +#ifdef ENABLE_HR_MODE + Word32 global_gain; +#else + Word16 global_gain; +#endif + Word16 global_gain_e; + Word32 tmp32; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processApplyGlobalGain_fx", sizeof(struct { + Counter i; + Word16 global_gain, global_gain_e; + Word32 tmp32; + })); +#endif + +#ifdef ENABLE_HR_MODE + /* 1 / (28 * log 2) is 0x797D in Q18, L_shl_pos by 7 results in Q25 tmp32 */ + /* round(2^31 / (28 * log10(2))) = 254778081 */ + //tmp32 = L_shl_pos(Mpy_32_16_lc3plus(254778081, add(global_gain_idx, global_gain_off)), 9); + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss(254778081, add(global_gain_idx, global_gain_off), &mh, &ml); + tmp32 = L_shl_pos(mh, 9) | L_deposit_l((shr((Word16)ml, 7)) & 0x1ff); + move16(); + /* Uses an argument in Q25 */ + global_gain = BASOP_Util_InvLog2_lc3plus(L_or(tmp32, (Word32)0xFE000000)); +#else + tmp32 = L_shl_pos(L_mult0(add(global_gain_idx, global_gain_off), 0x797D), 7); + /* Uses an argument in Q25 */ + global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, (Word32)0xFE000000))); +#endif + global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); + + FOR (i = 0; i < xLen; i++) + { +#ifdef ENABLE_HR_MODE + x[i] = Mpy_32_32_lc3plus(x[i], global_gain); +#else + x[i] = Mpy_32_16_lc3plus(x[i], global_gain); +#endif + move32(); + } + + *x_e = add(*x_e, global_gain_e); move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/ari_codec.c b/lib_lc3plus/ari_codec.c new file mode 100644 index 000000000..8092aa28e --- /dev/null +++ b/lib_lc3plus/ari_codec.c @@ -0,0 +1,2465 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + + +typedef struct +{ + Word16 inv_bin; + Word16 numbytes; + Word16 c_bp; + Word16 c_bp_side; + Word16 bytes; + Word16 b_left; + Word16 b_right; + Word16 enc; + Word16 sim_dec; + Word16 bfi; + Word16 be_bp_left; + Word16 be_bp_right; +} Pc_State_fx; + +typedef struct +{ + UWord32 ac_low_fx; + UWord32 ac_range_fx; + Word16 ac_cache_fx; + Word16 ac_carry_fx; + Word16 ac_carry_count_fx; +} Encoder_State_fx; + +typedef struct +{ + UWord32 ac_low_fx; + UWord32 ac_range_fx; + UWord32 ac_help_fx; + Word16 BER_detect; + Pc_State_fx pc; +} Decoder_State_fx; + +static void ac_dec_init_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_side, Word16 *mask_side, + Decoder_State_fx *st_fx /* i/o: Decoder State */ +); + +static __forceinline void pc_init_fx(Word16 n_pc, Word16 numbytes, Word16 be_bp_left, Word16 be_bp_right, Word16 L_spec, + Word16 enc, Word16 sim_dec, Word16 bfi, Pc_State_fx *pc /* i/o: Pc State */ +); +static __forceinline Word16 check_pc_bytes(Word16 *bp, Word16 *bp_side, Word16 *mask_side, Word16 cur_bin, + Word16 from_left, Pc_State_fx *pc /* i/o: Pc State */ +); + +static void ac_enc_init_fx(Encoder_State_fx *st_fx /* i/o: Encoder state */ +); + +static void ac_enc_shift_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx /* i/o: Encoder state */ +); + +static void write_indice_forward(UWord8 *ptr, Word16 bp, Word16 indice, Word16 numbits); + +static void ac_encode_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq /* i : Symbol probability */ +); + +static Word16 ac_enc_finish_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx /* i/o: Encoder state */ +); + +static Word16 ac_decode_fx( /* o : Decoded cumulative frequency */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 pki); +static Word16 ac_decode_tns_order( /* o : Decoded cumulative frequency */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 enable_lpc_weighting); +static Word16 ac_decode_tns_coef( /* o : Decoded cumulative frequency */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 pki); +static Word16 ac_dec_update_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_side, Word16 *mask_side, Word16 cur_bin, + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 cum_freq, /* i : Cumulative frequency */ + UWord32 sym_freq /* i : Symbol frequency */ +); + +/*************************************************************************/ + +# ifdef ENABLE_HR_MODE + +Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side_in, Word16 mask_side_in, Word16 nbbits, Word32 xq[], + Word16 *tns_order, Word16 tns_numfilters, Word16 *tns_idx, Word16 lastnz, + Word16 *codingdata, UWord8 *resBits, Word16 numResBits, Word16 lsbMode, + Word16 enable_lpc_weighting, Word8 *scratchBuffer) +{ + Word16 resbit, i1, i2; + + Dyn_Mem_Deluxe_In(Encoder_State_fx st; Word16 bp, bp_side, mask_side, extra_bits; + Word32 a1, b1, a1_i, b1_i, a1_msb, b1_msb; Word16 lev1; Word16 nbits_side; Word16 tmp; + Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Counter i, n, k, lev;); + + lsb = (Word16 *)scratchAlign(scratchBuffer, 0); /* size = 2 * lastnz */ + + /* Init */ + a1_i = 0; + move16(); + b1_i = 1; + move16(); + bp = 0; + move16(); + numResBitsEnc = 0; + move16(); + nlsbs = 0; + move16(); + ptr = bytes; + bp_side = bp_side_in; + move16(); + mask_side = mask_side_in; + move16(); + + /*Start Encoding*/ + ac_enc_init_fx(&st); + + /* TNS data */ + FOR (n = 0; n < tns_numfilters; n++) + { + IF (tns_order[n] > 0) + { + ac_encode_fx(ptr, &bp, &st, ac_tns_order_cumfreq[enable_lpc_weighting][tns_order[n] - 1], + ac_tns_order_freq[enable_lpc_weighting][tns_order[n] - 1]); + FOR (k = 0; k < tns_order[n]; k++) + { + ac_encode_fx(ptr, &bp, &st, ac_tns_coef_cumfreq[k][tns_idx[MAXLAG * n + k]], + ac_tns_coef_freq[k][tns_idx[MAXLAG * n + k]]); + } + } + } + + IF (lsbMode == 0) + { + + /*Main Loop through the 2-tuples*/ + FOR (k = 0; k < lastnz; k += 2) + { + IF (codingdata[1] < 0) + { + ac_encode_fx(ptr, &bp, &st, 0, + ari_spec_freq[ari_spec_lookup[codingdata[0]]][0]); + } + ELSE IF (codingdata[1] == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][codingdata[2]]); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[a1_i], 31)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[b1_i], 31)); + } + } + ELSE IF (sub(codingdata[1], 1) == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][VAL_ESC]); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]]); + write_bit_backward(ptr, &bp_side, &mask_side, L_and(xq[a1_i], 1)); + write_bit_backward(ptr, &bp_side, &mask_side, L_and(xq[b1_i], 1)); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[a1_i], 31)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[b1_i], 31)); + } + } + ELSE + { + a1 = L_abs(xq[a1_i]); + b1 = L_abs(xq[b1_i]); + FOR (lev = 0; lev < codingdata[1]; lev++) + { + lev1 = s_min(lev, 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC]); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(L_shr_pos(a1, lev), 1)); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(L_shr_pos(b1, lev), 1)); + } + lev1 = s_min(codingdata[1], 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]]); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[a1_i], 31)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[b1_i], 31)); + } + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /*end of the 2-tuples loop*/ + } + ELSE + { + /*Main Loop through the 2-tuples*/ + FOR (k = 0; k < lastnz; k += 2) + { + IF (codingdata[1] < 0) + { + ac_encode_fx(ptr, &bp, &st, 0, + ari_spec_freq[ari_spec_lookup[codingdata[0]]][0]); + } + ELSE IF (codingdata[1] == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][codingdata[2]]); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[a1_i], 31)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[b1_i], 31)); + } + } + ELSE IF (sub(codingdata[1], 1) == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][VAL_ESC]); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]]); + a1_msb = s_and(codingdata[2], 0x3); + tmp = L_and(xq[a1_i], 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (a1_msb == 0 && tmp > 0) + { + if (xq[a1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[a1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + IF (a1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[a1_i], 31)); + } + b1_msb = shr_pos(codingdata[2], 2); + tmp = L_and(xq[b1_i], 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (b1_msb == 0 && tmp > 0) + { + if (xq[b1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[b1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + IF (b1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[b1_i], 31)); + } + } + ELSE + { + a1 = L_abs(xq[a1_i]); + b1 = L_abs(xq[b1_i]); + a1_msb = L_shr_pos(a1, 1); + tmp = L_and(a1, 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (a1_msb == 0 && tmp > 0) + { + if (xq[a1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[a1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + b1_msb = L_shr_pos(b1, 1); + tmp = s_and(b1, 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (b1_msb == 0 && tmp > 0) + { + if (xq[b1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[b1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[0]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[0]]][VAL_ESC]); + FOR (lev = 1; lev < codingdata[1]; lev++) + { + lev1 = s_min(lev, 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC]); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(L_shr_pos(a1, lev), 1)); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(L_shr_pos(b1, lev), 1)); + } + lev1 = s_min(codingdata[1], 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]]); + IF (a1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[a1_i], 31)); + } + IF (b1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, L_lshr(xq[b1_i], 31)); + } + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /*end of the 2-tuples loop*/ + } + + /* Side bits (in sync with the decoder) */ + nbits_side = sub(nbbits, add(shl_pos(bp_side, 3), sub(norm_s(mask_side), 6))); + + /* Residual bits (in sync with the decoder) */ + extra_bits = sub(norm_ul(st.ac_range_fx), 6); + if (st.ac_cache_fx >= 0) + { + extra_bits = add(extra_bits, 8); + } + if (st.ac_carry_count_fx > 0) + { + extra_bits = add(extra_bits, shl_pos(st.ac_carry_count_fx, 3)); + } + + n = s_max(sub(nbbits, add(shl_pos(bp, 3), add(extra_bits, nbits_side))), 0); + move16(); + + IF (lsbMode == 0) + { + numResBitsEnc = s_min(numResBits, n); + FOR (i = 0; i < numResBitsEnc; i++) + { + resbit = 0; move16(); + i1 = shr(i, RESBITS_PACK_SHIFT); + i2 = s_and(i, RESBITS_PACK_MASK); + if (s_and(resBits[i1], shl(1, i2))) + { + resbit = 1; + } + write_bit_backward(ptr, &bp_side, &mask_side, resbit); + } + } + ELSE + { + nlsbs = s_min(nlsbs, n); + FOR (k = 0; k < nlsbs; k++) + { + write_bit_backward(ptr, &bp_side, &mask_side, lsb[k]); + } + } + + /* End arithmetic coder, overflow management */ + extra_bits = ac_enc_finish_fx(ptr, &bp, &st); + + /* Fill bits (for debugging, the exact number of fill bits cannot be computed in the decoder)*/ + fill_bits = nbbits - (bp * 8 + extra_bits + nbits_side + nlsbs + numResBitsEnc); + + Dyn_Mem_Deluxe_Out(); + + return fill_bits; +} + +# else /* ENABLE_HR_MODE */ + +Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side_in, Word16 mask_side_in, Word16 nbbits, Word16 xq[], + Word16 *tns_order, Word16 tns_numfilters, Word16 *tns_idx, Word16 lastnz, + Word16 *codingdata, UWord8 *resBits, Word16 numResBits, Word16 lsbMode, + Word16 enable_lpc_weighting, Word8 *scratchBuffer) +{ +#ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In(Encoder_State_fx st; Word16 bp, bp_side, mask_side, extra_bits; + Word16 a1, b1, a1_i, b1_i, a1_msb, b1_msb; Word16 lev1; Word16 nbits_side; Word16 tmp; + Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Counter i, n, k, lev; + ); +#else + Dyn_Mem_Deluxe_In(Encoder_State_fx st; Word16 bp, bp_side, mask_side, extra_bits; + Word16 a1, b1, a1_i, b1_i, a1_msb, b1_msb; Word16 lev1; Word16 nbits_side; Word16 tmp; + Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Counter i, n, k, lev; + ); +#endif + + + lsb = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN * 2 bytes */ + + /* Init */ + a1_i = 0; + move16(); + b1_i = 1; + move16(); + bp = 0; + move16(); + numResBitsEnc = 0; + move16(); + nlsbs = 0; + move16(); + ptr = bytes; + bp_side = bp_side_in; + move16(); + mask_side = mask_side_in; + move16(); + + /*Start Encoding*/ + ac_enc_init_fx(&st); + + /* TNS data */ + FOR (n = 0; n < tns_numfilters; n++) + { + IF (tns_order[n] > 0) + { + ac_encode_fx(ptr, &bp, &st, ac_tns_order_cumfreq[enable_lpc_weighting][tns_order[n] - 1], + ac_tns_order_freq[enable_lpc_weighting][tns_order[n] - 1]); + FOR (k = 0; k < tns_order[n]; k++) + { + ac_encode_fx(ptr, &bp, &st, ac_tns_coef_cumfreq[k][tns_idx[MAXLAG * n + k]], + ac_tns_coef_freq[k][tns_idx[MAXLAG * n + k]]); + } + } + } + + IF (lsbMode == 0) + { + + /*Main Loop through the 2-tuples*/ + FOR (k = 0; k < lastnz; k += 2) + { + IF (codingdata[1] < 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][0], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][0]); + } + ELSE IF (codingdata[1] == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][codingdata[2]]); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[a1_i], 15)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[b1_i], 15)); + } + } + ELSE IF (sub(codingdata[1], 1) == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][VAL_ESC]); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]]); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(xq[a1_i], 1)); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(xq[b1_i], 1)); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[a1_i], 15)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[b1_i], 15)); + } + } + ELSE + { + a1 = abs_s(xq[a1_i]); + b1 = abs_s(xq[b1_i]); + FOR (lev = 0; lev < codingdata[1]; lev++) + { + lev1 = s_min(lev, 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC]); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(shr_pos(a1, lev), 1)); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(shr_pos(b1, lev), 1)); + } + lev1 = s_min(codingdata[1], 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]]); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[a1_i], 15)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[b1_i], 15)); + } + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /*end of the 2-tuples loop*/ + } + ELSE + { + /*Main Loop through the 2-tuples*/ + FOR (k = 0; k < lastnz; k += 2) + { + IF (codingdata[1] < 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][0], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][0]); + } + ELSE IF (codingdata[1] == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][codingdata[2]]); + IF (xq[a1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[a1_i], 15)); + } + IF (xq[b1_i] != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[b1_i], 15)); + } + } + ELSE IF (sub(codingdata[1], 1) == 0) + { + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0]]][VAL_ESC]); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[1]]][codingdata[2]]); + a1_msb = s_and(codingdata[2], 0x3); + tmp = s_and(xq[a1_i], 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (a1_msb == 0 && tmp > 0) + { + if (xq[a1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[a1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + IF (a1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[a1_i], 15)); + } + b1_msb = shr_pos(codingdata[2], 2); + tmp = s_and(xq[b1_i], 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (b1_msb == 0 && tmp > 0) + { + if (xq[b1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[b1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + IF (b1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[b1_i], 15)); + } + } + ELSE + { + a1 = abs_s(xq[a1_i]); + b1 = abs_s(xq[b1_i]); + a1_msb = shr_pos(a1, 1); + tmp = s_and(a1, 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (a1_msb == 0 && tmp > 0) + { + if (xq[a1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[a1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + b1_msb = shr_pos(b1, 1); + tmp = s_and(b1, 1); + lsb[nlsbs++] = tmp; + move16(); + test(); + IF (b1_msb == 0 && tmp > 0) + { + if (xq[b1_i] > 0) + { + lsb[nlsbs++] = 0; + move16(); + } + if (xq[b1_i] < 0) + { + lsb[nlsbs++] = 1; + move16(); + } + } + ac_encode_fx(ptr, &bp, &st, ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[0]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[0]]][VAL_ESC]); + FOR (lev = 1; lev < codingdata[1]; lev++) + { + lev1 = s_min(lev, 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][VAL_ESC]); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(shr_pos(a1, lev), 1)); + write_bit_backward(ptr, &bp_side, &mask_side, s_and(shr_pos(b1, lev), 1)); + } + lev1 = s_min(codingdata[1], 3); + ac_encode_fx(ptr, &bp, &st, + ari_spec_cumfreq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]], + ari_spec_freq[ari_spec_lookup[codingdata[0] + Tab_esc_nb[lev1]]][codingdata[2]]); + IF (a1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[a1_i], 15)); + } + IF (b1_msb != 0) + { + write_bit_backward(ptr, &bp_side, &mask_side, lshr(xq[b1_i], 15)); + } + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /*end of the 2-tuples loop*/ + } + + /* Side bits (in sync with the decoder) */ + nbits_side = sub(nbbits, add(shl_pos(bp_side, 3), sub(norm_s(mask_side), 6))); + + /* Residual bits (in sync with the decoder) */ + extra_bits = sub(norm_ul(st.ac_range_fx), 6); + if (st.ac_cache_fx >= 0) + { + extra_bits = add(extra_bits, 8); + } + if (st.ac_carry_count_fx > 0) + { + extra_bits = add(extra_bits, shl_pos(st.ac_carry_count_fx, 3)); + } + + n = s_max(sub(nbbits, add(shl_pos(bp, 3), add(extra_bits, nbits_side))), 0); + move16(); + + IF (lsbMode == 0) + { + numResBitsEnc = s_min(numResBits, n); + FOR (i = 0; i < numResBitsEnc; i++) + { + FOR (i = 0; i < numResBitsEnc; i++) + { + write_bit_backward(ptr, &bp_side, &mask_side, resBits[i]); + } + } + } + ELSE + { + nlsbs = s_min(nlsbs, n); + FOR (k = 0; k < nlsbs; k++) + { + write_bit_backward(ptr, &bp_side, &mask_side, lsb[k]); + } + } + + /* End arithmetic coder, overflow management */ + extra_bits = ac_enc_finish_fx(ptr, &bp, &st); + + /* Fill bits (for debugging, the exact number of fill bits cannot be computed in the decoder)*/ + fill_bits = nbbits - (bp * 8 + extra_bits + nbits_side + nlsbs + numResBitsEnc); + + Dyn_Mem_Deluxe_Out(); + return fill_bits; +} + +#endif /* ENABLE_HR_MODE */ + +void processAriDecoder_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 L_spec, + Word16 fs_idx, Word16 enable_lpc_weighting, Word16 tns_numfilters, Word16 lsbMode, + Word16 lastnz, Word16 *bfi, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, + Word16 frame_dms, + Word16 n_pc, Word16 be_bp_left, Word16 be_bp_right, Word16 mode, Word16 *spec_inv_idx, + Word16 *b_left, + Word16 *resBits, +# ifdef ENABLE_HR_MODE + Word32 *x, +# else + Word16 *x, +# endif + Word16 *nf_seed, UWord8 *resQdata, Word16 *tns_idx, Word16 *zero_frame, Word8 *scratchBuffer +# ifdef ENABLE_HR_MODE + , Word16 hrmode +# endif +) +{ + Decoder_State_fx st; +# ifdef ENABLE_HR_MODE + Word16 resbit, i1, i2; + Word32 a, b; +# else + Word16 a, b; +# endif + Word16 t, a1, b1, a1_i, b1_i, bp; + Word16 esc_nb; + Word16 rateFlag; + Word16 r; + Word16 nt_half; + Word16 c; + Word16 nbits_side, extra_bits, nbits_ari; + UWord8 * ptr; + Word32 tmp32; + Word16 lsb_ind_c; + Word16 * lsb_ind; + Word16 tmp; + Counter n, k, lev; + Counter i; + Word16 max_lev = 14; + +#ifdef DYNMEM_COUNT +struct _dynmem +{ +Decoder_State_fx st; + Pc_State_fx pc; + Word16 resbit, i1, i2; +# ifdef ENABLE_HR_MODE + Word32 a, b; +# else + Word16 a, b; +# endif + Word16 t, a1, b1, a1_i, b1_i, bp; + Word16 esc_nb; + Word16 rateFlag; + Word16 r; + Word16 nt_half; + Word16 c; + Word16 nbits_side, extra_bits, nbits_ari; + UWord8 * ptr; + Word32 tmp32; + Word16 lsb_ind_c; + Word16 * lsb_ind; + Word16 tmp; + Counter i, n, k, lev; + }; + Dyn_Mem_In("processAriDecoder_fx", sizeof(struct _dynmem)); +#endif + +# ifdef ENABLE_HR_MODE + if (hrmode == 1) + { + max_lev = max_lev + 8; + } +# endif + + lsb_ind = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size 2 * MAX_LEN bytes */ + + /* Rate flag */ + rateFlag = 0; + move16(); +# ifdef ENABLE_HR_MODE + if (fs_idx != 5) /* Don't update rateFlag for 96000 Hz */ +# endif + { + if (sub(nbbits, add(160, DEPR_i_mult(fs_idx, 160))) > 0) + { + rateFlag = 2 << NBITS_CONTEXT; + move16(); + } + } + + pc_init_fx(n_pc, shr_pos(nbbits, 3), be_bp_left, be_bp_right, L_spec, mode==1, mode==2, *bfi, &st.pc); + + /* Init */ + nt_half = shr_pos(L_spec, 1); + c = 0; + move16(); + t = 0; + move16(); + a1_i = 0; + move16(); + b1_i = 1; + move16(); + bp = 0; + move16(); + if (mode != 1) + { + bp = add(bp, st.pc.bytes); + move16(); + } + *spec_inv_idx = L_spec; + move16(); + *b_left = -1; + move16(); + lsb_ind_c = 0; + move16(); + +ptr = bytes; + +/* Start Decoding */ +ac_dec_init_fx(ptr, &bp, bp_side, mask_side, &st); + + /* Decode TNS data */ + tmp = MAXLAG; +IF (sub(frame_dms, 25) == 0) +{ +tmp = shr_pos(tmp, 1); +} +IF (sub(frame_dms, 50) == 0) +{ +tmp = shr_pos(tmp, 1); +} + + FOR (n = 0; n < tns_numfilters; n++) + { + IF (tns_order[n] > 0) + { + tns_order[n] = ac_decode_tns_order(&st, enable_lpc_weighting); + move16(); + tns_order[n] = add(tns_order[n], 1); + move16(); + IF (tns_order[n] > tmp) + { + GOTO ber_detect; + } + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, 0, &st, + ac_tns_order_cumfreq[enable_lpc_weighting][tns_order[n] - 1], + ac_tns_order_freq[enable_lpc_weighting][tns_order[n] - 1]) != 0) + { + GOTO ber_detect; + } + FOR (k = 0; k < tns_order[n]; k++) + { + IF (sub(*bp_side, bp) < 0) + { + GOTO ber_detect; + } + tns_idx[MAXLAG * n + k] = ac_decode_tns_coef(&st, k); + move16(); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, 0, &st, + ac_tns_coef_cumfreq[k][tns_idx[MAXLAG * n + k]], + ac_tns_coef_freq[k][tns_idx[MAXLAG * n + k]]) != 0) + { + GOTO ber_detect; + } + } + } + } + IF (st.BER_detect > 0) + { + GOTO ber_detect; + } + +IF (lsbMode == 0) +{ + +/*Main Loop through the 2-tuples*/ +FOR (k = 0; k < lastnz; k += 2) +{ + +/* Get context */ +t = add(c, rateFlag); +if (sub(k, nt_half) > 0) +{ +t = add(t, 1 << NBITS_CONTEXT); +} + + r = ac_decode_fx(&st, ari_spec_lookup[t]); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t]][r], + ari_spec_freq[ari_spec_lookup[t]][r]) != 0) + { + GOTO ber_detect; + } + + IF (r == 0) + { + x[a1_i] = 0; + move16(); + x[b1_i] = 0; + move16(); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (sub(r, VAL_ESC) < 0) + { + a = s_and(r, 0x3); + b = shr_pos(r, 2); + c = add(shl_pos(s_and(c, 0xf), 4), add(add(a, b), 1)); + IF (a > 0) + { +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} + if (read_bit(ptr, bp_side, mask_side) != 0) + { + a = negate(a); + } + } + x[a1_i] = a; + move16(); + IF (b > 0) + { +if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} + if (read_bit(ptr, bp_side, mask_side) != 0) + { + b = negate(b); + } + } + x[b1_i] = b; + move16(); + } + ELSE + { +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ +GOTO ber_detect; +} +a = read_bit(ptr, bp_side, mask_side); +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ +GOTO ber_detect; +} + b = read_bit(ptr, bp_side, mask_side); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[1]]); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, + ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[1]]][r], + ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[1]]][r]) != 0) + { + GOTO ber_detect; + } + IF (sub(r, VAL_ESC) < 0) + { + a1 = s_and(r, 0x3); + b1 = shr_pos(r, 2); + a = add(shl_pos(a1, 1), a); + b = add(shl_pos(b1, 1), b); + IF (a > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { + a = negate(a); + } + } + x[a1_i] = a; + move16(); + IF (b > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { + b = negate(b); + } + } + x[b1_i] = b; + move16(); + c = add(shl_pos(s_and(c, 0xf), 4), add(shl_pos(add(a1, b1), 1), 1)); + } + ELSE + { +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} +a = add(shl_pos(read_bit(ptr, bp_side, mask_side), 1), a); +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} + b = add(shl_pos(read_bit(ptr, bp_side, mask_side), 1), b); + FOR (lev = 2; lev < max_lev; lev++) + { + esc_nb = s_min(lev, 3); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[esc_nb]]); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, + ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r], + ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r]) != 0) + { + GOTO ber_detect; + } + IF (sub(r, VAL_ESC) < 0) + { + BREAK; + } + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + +# ifdef ENABLE_HR_MODE + a = L_add(L_shl(read_bit(ptr, bp_side, mask_side), lev), a); +# else + a = add(shl(read_bit(ptr, bp_side, mask_side), lev), a); +# endif + + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } +# ifdef ENABLE_HR_MODE + b = L_add(L_shl(read_bit(ptr, bp_side, mask_side), lev), b); +# else + b = add(shl(read_bit(ptr, bp_side, mask_side), lev), b); +# endif + } + /* check for bitflip */ + IF (sub(lev, max_lev) == 0) + { + GOTO ber_detect; + } + + b1 = shr_pos(r, 2); + a1 = s_and(r, 0x3); + +# ifdef ENABLE_HR_MODE + a = L_add(L_shl(a1, lev), a); + b = L_add(L_shl(b1, lev), b); +# else + a = add(shl(a1, lev), a); + b = add(shl(b1, lev), b); +# endif + IF (a > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { +# ifdef ENABLE_HR_MODE + a = L_negate(a); +# else + a = negate(a); +# endif + } + } + x[a1_i] = a; + move16(); + IF (b > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { +# ifdef ENABLE_HR_MODE + b = L_negate(b); +# else + b = negate(b); +# endif + } + } + x[b1_i] = b; + move16(); + c = add(shl_pos(s_and(c, 0xf), 4), add(esc_nb, 12)); + } + } + + test(); + test(); + IF ((sub(sub(bp, *bp_side), 3) > 0 && sub(st.pc.c_bp, st.pc.c_bp_side) == 0) || st.BER_detect > 0) +{ +GOTO ber_detect; +} + +a1_i += 2; +b1_i += 2; +} +} +ELSE +{ +/*Main Loop through the 2-tuples*/ +FOR (k = 0; k < lastnz; k += 2) +{ + +/* Get context */ +t = add(c, rateFlag); +if (sub(k, nt_half) > 0) +{ +t = add(t, 1 << NBITS_CONTEXT); +} + + r = ac_decode_fx(&st, ari_spec_lookup[t]); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, ari_spec_cumfreq[ari_spec_lookup[t]][r], + ari_spec_freq[ari_spec_lookup[t]][r]) != 0) + { + GOTO ber_detect; + } + + IF (r == 0) + { + x[a1_i] = 0; + move16(); + x[b1_i] = 0; + move16(); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (sub(r, VAL_ESC) < 0) + { + a = s_and(r, 0x3); + b = shr_pos(r, 2); + c = add(shl_pos(s_and(c, 0xf), 4), add(add(a, b), 1)); + IF (a > 0) + { +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} + if (read_bit(ptr, bp_side, mask_side) != 0) + { + a = negate(a); + } + } + x[a1_i] = a; + move16(); + IF (b > 0) + { +if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} + if (read_bit(ptr, bp_side, mask_side) != 0) + { + b = negate(b); + } + } + x[b1_i] = b; + move16(); + } + ELSE + { + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[1]]); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, + ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[1]]][r], + ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[1]]][r]) != 0) + { + GOTO ber_detect; + } + IF (sub(r, VAL_ESC) < 0) + { + a1 = s_and(r, 0x3); + b1 = shr_pos(r, 2); + a = shl_pos(a1, 1); + b = shl_pos(b1, 1); + IF (a > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { + a = negate(a); + } + } + x[a1_i] = a; + move16(); + IF (b > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { + b = negate(b); + } + } + x[b1_i] = b; + move16(); + c = add(shl_pos(s_and(c, 0xf), 4), add(shl_pos(add(a1, b1), 1), 1)); + lsb_ind[lsb_ind_c++] = k; + move16(); + } + ELSE + { +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} +a = shl_pos(read_bit(ptr, bp_side, mask_side), 1); +if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) +{ + GOTO ber_detect; +} + b = shl_pos(read_bit(ptr, bp_side, mask_side), 1); + FOR (lev = 2; lev < max_lev; lev++) + { + esc_nb = s_min(lev, 3); + r = ac_decode_fx(&st, ari_spec_lookup[t + Tab_esc_nb[esc_nb]]); + if (ac_dec_update_fx(ptr, &bp, bp_side, mask_side, k, &st, + ari_spec_cumfreq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r], + ari_spec_freq[ari_spec_lookup[t + Tab_esc_nb[esc_nb]]][r]) != 0) + { + GOTO ber_detect; + } + IF (sub(r, VAL_ESC) < 0) + { + BREAK; + } + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } +# ifdef ENABLE_HR_MODE + a = L_add(L_shl(read_bit(ptr, bp_side, mask_side), lev), a); +# else + a = add(shl(read_bit(ptr, bp_side, mask_side), lev), a); +# endif + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } +# ifdef ENABLE_HR_MODE + b = L_add(L_shl(read_bit(ptr, bp_side, mask_side), lev), b); +# else + b = add(shl(read_bit(ptr, bp_side, mask_side), lev), b); +# endif + } + /* check for bitflip */ + IF (sub(lev, max_lev) == 0) + { + GOTO ber_detect; + } + + b1 = shr_pos(r, 2); + a1 = s_and(r, 0x3); +# ifdef ENABLE_HR_MODE + a = L_add(L_shl(a1, lev), a); + b = L_add(L_shl(b1, lev), b); +# else + a = add(shl(a1, lev), a); + b = add(shl(b1, lev), b); +# endif + IF (a > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, a1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { +# ifdef ENABLE_HR_MODE + a = L_negate(a); +# else + a = negate(a); +# endif + } + } + x[a1_i] = a; + move16(); + IF (b > 0) + { + if (check_pc_bytes(&bp, bp_side, mask_side, b1_i, 0, &st.pc) != 0) + { + GOTO ber_detect; + } + if (read_bit(ptr, bp_side, mask_side) != 0) + { +# ifdef ENABLE_HR_MODE + b = L_negate(b); +# else + b = negate(b); +# endif + } + } + x[b1_i] = b; + move16(); + c = add(shl_pos(s_and(c, 0xf), 4), add(esc_nb, 12)); + lsb_ind[lsb_ind_c++] = k; + move16(); + } + } + + test(); + test(); + IF ((sub(sub(bp, *bp_side), 3) > 0 && sub(st.pc.c_bp, st.pc.c_bp_side) == 0) || st.BER_detect > 0) +{ +GOTO ber_detect; +} + +a1_i += 2; +b1_i += 2; +} +} + +IF (L_spec > k) +{ +basop_memset(&x[k], 0, (L_spec - k) * sizeof(*x)); +} + + nbits_side = sub(nbbits, add(shl_pos(*bp_side, 3), sub(norm_s(*mask_side), 6))); + extra_bits = sub(norm_ul(st.ac_range_fx), 6); + nbits_ari = shl_pos(sub(bp, 3), 3); +IF (mode != 1) +{ +IF (st.pc.c_bp == 0) +{ +nbits_ari = shl_pos(sub(sub(bp, st.pc.bytes), 3), 3); +} +ELSE +{ +nbits_ari = shl_pos(add(bp, sub(sub(st.pc.b_left, st.pc.bytes), 3)), 3); +} + + IF (st.pc.c_bp_side != 0) + { + nbits_side = sub(add(sub(nbbits, shl_pos(st.pc.b_left, 3)), shl_pos(sub(st.pc.bytes, *bp_side), 3)), + sub(norm_s(*mask_side), 6)); + } + } + + n = sub(nbbits, add(nbits_ari, add(extra_bits, nbits_side))); + move16(); + +IF (n < 0) +{ +GOTO ber_detect; +} + + IF (lsbMode == 0) + { + *resBits = n; + move16(); + i=0; + +#ifdef ENABLE_HR_MODE + FOR (k = 0; k < L_spec; k++) + { + IF (x[k] != 0) + { + IF (n == 0) + { + BREAK; + } + if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) + { + GOTO ber_detect_res; + } + i1 = shr(i, RESBITS_PACK_SHIFT); + i2 = s_and(i, RESBITS_PACK_MASK); + resbit = read_bit(ptr, bp_side, mask_side); + if (resbit) + { + resQdata[i1] = (UWord8) s_or(resQdata[i1], shl(1, i2)); + } + i = add(i, 1); + move16(); + n = sub(n, 1); + } + } +#else + FOR (k = 0; k < L_spec; k++) + { + IF (x[k] != 0) + { + IF (n == 0) + { + BREAK; + } + + if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) + { + GOTO ber_detect_res; + } + + *resQdata++ = (UWord8) read_bit(ptr, bp_side, mask_side); + move16(); + n = sub(n, 1); + } + } +#endif + +# ifdef ENABLE_HR_MODE + if (hrmode) + { + Word16 idx_len = sub(*resBits, n); /* Number of nonzero bits */ + Word16 idx_len_lim = idx_len * EXT_RES_ITER_MAX; + + Word16 res_bits_hrmode = s_min(idx_len_lim, *resBits) - idx_len; + /* idx_len bits have been read in the previous loop */ + + for (k = 0; k < res_bits_hrmode; k++) + { + if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) + { + GOTO ber_detect_res; + } + i1 = shr(i, RESBITS_PACK_SHIFT); + i2 = s_and(i, RESBITS_PACK_MASK); + resbit = read_bit(ptr, bp_side, mask_side); + if (resbit) + { + resQdata[i1] = (UWord8) s_or(resQdata[i1], shl(1, i2)); + } + i = add(i, 1); + move16(); + n = sub(n, 1); + } + } +# endif + + *resBits = sub(*resBits, n); + } + ELSE + { + *resBits = 0; + FOR (k = 0; k < lsb_ind_c; k++) + { + a = x[lsb_ind[k]]; + move16(); + IF (n == 0) + { + BREAK; + } +if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) +{ +GOTO ber_detect_res; +} + tmp = read_bit(ptr, bp_side, mask_side); + n = sub(n, 1); + IF (tmp > 0) + { +# ifdef ENABLE_HR_MODE + if (a > 0) + { + a = L_add(a, 1); + } + if (a < 0) + { + a = L_sub(a, 1); + } +# else + if (a > 0) + { + a = add(a, 1); + } + if (a < 0) + { + a = sub(a, 1); + } +# endif + IF (a == 0) + { + IF (n == 0) + { + BREAK; + } + a = 1; +if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) +{ + GOTO ber_detect_res; +} +if (read_bit(ptr, bp_side, mask_side) != 0) +{ + a = negate(a); +} +n = sub(n, 1); +} +} + + x[lsb_ind[k]] = a; + move16(); + b = x[lsb_ind[k] + 1]; + move16(); + IF (n == 0) + { + BREAK; + } +if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) +{ +GOTO ber_detect_res; +} + tmp = read_bit(ptr, bp_side, mask_side); + n = sub(n, 1); + IF (tmp > 0) + { +# ifdef ENABLE_HR_MODE + if (b > 0) + { + b = L_add(b, 1); + } + if (b < 0) + { + b = L_sub(b, 1); + } +# else + if (b > 0) + { + b = add(b, 1); + } + if (b < 0) + { + b = sub(b, 1); + } +# endif + IF (b == 0) + { + IF (n == 0) + { + BREAK; + } + b = 1; +if (check_pc_bytes(&bp, bp_side, mask_side, st.pc.inv_bin, 0, &st.pc) != 0) +{ + GOTO ber_detect_res; +} + if (read_bit(ptr, bp_side, mask_side) != 0) + { + b = negate(b); + } + n = sub(n, 1); + } + } + x[lsb_ind[k] + 1] = b; + move16(); + } + } + +/* Noise Filling seed */ + tmp32 = L_deposit_l(0); + FOR (i = 0; i < L_spec; i++) + { +# ifdef ENABLE_HR_MODE + tmp32 = L_mac0(tmp32, L_and(L_abs(x[i]), 32767), i); +# else + tmp32 = L_mac0(tmp32, abs_s(x[i]), i); +# endif + } + *nf_seed = extract_l(tmp32); + move16(); + + /* Detect zero frame */ + test(); + test(); + test(); + test(); + IF (sub(lastnz, 2) == 0 && sub(x[0], 0) == 0 && sub(x[1], 0) == 0 && sub(gg_idx, 0) == 0 && sub(fac_ns_idx, 7) == 0) + { + *zero_frame = 1; + move16(); + } + ELSE + { + *zero_frame = 0; + move16(); + } + +IF (mode == 1) + { + IF (st.pc.bytes > 0) + { + IF (sub(st.pc.b_left, shr_pos(nbbits, 3)) > 0) + { + *b_left = sub(*bp_side, st.pc.bytes); + } + } + } +IF (mode == 2) +{ +IF (st.pc.bytes > 0) +{ +IF (sub(st.pc.b_left, shr_pos(nbbits,3)) > 0) +{ +*b_left = *bp_side; +} +} +} + +IF (sub(*bfi, 2) == 0) +{ +IF (sub(*spec_inv_idx, L_spec) == 0) +{ +*bfi = 0; +} +} +GOTO bail; + +/* goto for bit error handling */ +ber_detect: + *bfi = 1; + move16(); + *b_left = st.pc.b_left; + move16(); + test(); + IF (st.pc.inv_bin > 0 && sub(st.pc.inv_bin, L_spec) <= 0) + { + *spec_inv_idx = st.pc.inv_bin; + move16(); + *bfi = 2; + move16(); + *resBits = 0; + move16(); + *zero_frame = 0; + move16(); + /* Noise Filling seed */ + tmp32 = L_deposit_l(0); + FOR (i = 0; i < *spec_inv_idx; i++) + { + tmp32 = L_mac0(tmp32, abs_s(x[i]), i); + } + *nf_seed = extract_l(tmp32); + move16(); + } +GOTO bail; + +/* goto for bit error handling in residual signal */ +ber_detect_res: + *b_left = st.pc.b_left; + move16(); + *resBits = 0; + move16(); + *bfi = 0; + move16(); + *zero_frame = 0; + move16(); + /* Noise Filling seed */ + tmp32 = L_deposit_l(0); + FOR (i = 0; i < *spec_inv_idx; i++) + { + tmp32 = L_mac0(tmp32, abs_s(x[i]), i); + } + *nf_seed = extract_l(tmp32); + move16(); + GOTO bail; + +/* goto, because of dynmem out */ +bail: +Dyn_Mem_Deluxe_Out(); +} + + +void processAriDecoderScaling_fx( +# ifdef ENABLE_HR_MODE + Word32 *datain, +# else + Word16 *data16, +# endif + Word16 dataLen, Word32 *data32, Word16 *data_e) +{ + Counter i; + +# ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In(Word16 shift; Word32 tmp, x_min, x_max;); +# else + Dyn_Mem_Deluxe_In(Word16 shift; Word16 tmp, x_min, x_max;); +# endif + + +#ifdef ENABLE_HR_MODE + x_max = 0; + move32(); + x_min = 0; + move32(); +#else + x_max = 0; + move16(); + x_min = 0; + move16(); +#endif + + FOR (i = 0; i < dataLen; i++) + { +#ifdef ENABLE_HR_MODE + if (datain[i] > 0) + x_max = L_max(x_max, datain[i]); + if (datain[i] < 0) + x_min = L_min(x_min, datain[i]); +#else + if (data16[i] > 0) + x_max = s_max(x_max, data16[i]); + if (data16[i] < 0) + x_min = s_min(x_min, data16[i]); +#endif + } + +#ifdef ENABLE_HR_MODE + tmp = L_max(x_max, L_negate(x_min)); + shift = norm_l(tmp); + if (tmp == 0) + { + shift = 31; + move32(); + } +#else + tmp = s_max(x_max, negate(x_min)); + shift = norm_s(tmp); + if (tmp == 0) + { + shift = 15; + move16(); + } +#endif + + FOR (i = 0; i < dataLen; i++) + { +#ifdef ENABLE_HR_MODE + data32[i] = L_shl_pos(datain[i], shift); +#else + data32[i] = L_shl_pos(L_deposit_h(data16[i]), shift); +#endif + } + +#ifdef ENABLE_HR_MODE + *data_e = sub(31, shift); + move16(); +#else + *data_e = sub(15, shift); + move16(); +#endif + + Dyn_Mem_Deluxe_Out(); +} + + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + +/*************************************************************************/ + +static __forceinline UWord32 UL_addNs24(UWord32 UL_var1, UWord32 UL_var2, UWord16 *wrap) +{ + return UL_lshr(UL_addNs(UL_lshl(UL_var1, 8), UL_lshl(UL_var2, 8), wrap), 8); +} +#ifdef ENABLE_HR_MODE +Word16 find_last_nz_pair(const Word32 x[], Word16 length) +#else +Word16 find_last_nz_pair(const Word16 x[], Word16 length) +#endif +{ + Dyn_Mem_Deluxe_In(Word16 last_nz, lobs[4]; Counter stage, i;); + + lobs[0] = 4; + move16(); + lobs[1] = shr_pos(length, 1); /* length/2 */ + move16(); + lobs[2] = add(lobs[1], shr_pos(length, 2)); + move16(); + lobs[3] = add(lobs[2], shr_pos(length, 3)); + move16(); + + last_nz = 0; + move16(); + i = length; + move16(); + FOR (stage = 3; stage >= 0; --stage) + { + /* unmapped kernel */ + FOR (; i >= lobs[stage]; i -= 2) + { + if (x[i - 2] != 0) + { + last_nz = s_max(last_nz, i); + } + if (x[i - 1] != 0) + { + last_nz = s_max(last_nz, i); + } + } + IF (last_nz > 0) + { + BREAK; + } + } + + Dyn_Mem_Deluxe_Out(); + return s_max(last_nz, 2); +} + + +void write_bit_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 bit) +{ + if (bit > 0) + { + ptr[*bp] = (UWord8)s_or((Word16)ptr[*bp], *mask); + move16(); + } + *mask = lshl_pos(*mask, 1); + move16(); + if (sub(*mask, 0x100) == 0) + { + *mask = 1; + move16(); + } + if (sub(*mask, 1) == 0) + { + *bp = sub(*bp, 1); + move16(); + } +} + + +void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, Word16 numbits) +{ + Dyn_Mem_Deluxe_In(Counter k; Word16 bit;); + + FOR (k = 0; k < numbits; k++) + { + bit = s_and(indice, 1); + write_bit_backward(ptr, bp, mask, bit); + indice = lshr(indice, 1); + } + + Dyn_Mem_Deluxe_Out(); +} + + +static __forceinline void write_indice_forward(UWord8 *ptr, Word16 bp, Word16 indice, Word16 numbits) +{ + Dyn_Mem_Deluxe_In(Counter k; Word16 bit, mask, tmp;); + + tmp = (Word16)ptr[bp]; + move16(); + mask = 0x80; + move16(); + FOR (k = 0; k < numbits; k++) + { + bit = s_and(indice, mask); + tmp = s_or(tmp, mask); + if (bit == 0) + { + tmp = sub(tmp, mask); + } + mask = lshr(mask, 1); + } + ptr[bp] = (UWord8)tmp; + move16(); + + Dyn_Mem_Deluxe_Out(); +} + +static __forceinline void ac_enc_init_fx(Encoder_State_fx *st_fx) /* i/o: Encoder state */ +{ + st_fx->ac_low_fx = L_deposit_l(0); + move32(); + st_fx->ac_range_fx = 0x00ffffff; + move32(); + st_fx->ac_cache_fx = -1; + move16(); + st_fx->ac_carry_fx = 0; + move16(); + st_fx->ac_carry_count_fx = 0; + move16(); +} + +static __forceinline void ac_enc_shift_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx) /* i/o: Encoder state */ +{ + test(); + L_sub(0, 0); /* For comparision in if */ + IF (st_fx->ac_low_fx < (0x00ff0000UL) || sub(st_fx->ac_carry_fx, 1) == 0) + { + IF (st_fx->ac_cache_fx >= 0) + { + ptr[(*bp)++] = (UWord8)add(st_fx->ac_cache_fx, st_fx->ac_carry_fx); + move16(); + } + + WHILE (st_fx->ac_carry_count_fx > 0) + { + ptr[(*bp)++] = (UWord8)s_and(add(st_fx->ac_carry_fx, 0xff), 255); + move16(); + st_fx->ac_carry_count_fx = sub(st_fx->ac_carry_count_fx, 1); + move16(); + } + + st_fx->ac_cache_fx = u_extract_l(UL_lshr_pos(st_fx->ac_low_fx, 16)); + move16(); + st_fx->ac_carry_fx = 0; + move16(); + } + ELSE + { + st_fx->ac_carry_count_fx = add(st_fx->ac_carry_count_fx, 1); + move16(); + } + st_fx->ac_low_fx = UL_and(UL_lshl_pos(st_fx->ac_low_fx, 8), 0x00ffffff); + move32(); +} + +static __forceinline void ac_encode_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq) /* i : Symbol probability */ +{ + Dyn_Mem_Deluxe_In(UWord32 r, tmp; UWord16 carry;); + + r = UL_lshr_pos(st_fx->ac_range_fx, 10); + tmp = UL_Mpy_32_32(r, cum_freq); + + assert(r < (1U << 24)); + assert(cum_freq < (1U << 24)); + assert(tmp < (1U << 24)); + assert(st_fx->ac_low_fx < (1U << 24)); + st_fx->ac_low_fx = UL_addNs24(st_fx->ac_low_fx, tmp, &carry); + move32(); + + if (carry != 0) + { + st_fx->ac_carry_fx = carry; + move16(); + } + + st_fx->ac_range_fx = UL_Mpy_32_32(r, sym_freq); + move32(); + + assert(cum_freq < (1U << 24)); + assert(st_fx->ac_range_fx < (1U << 24)); + WHILE (st_fx->ac_range_fx < (1U << 16)) + { + L_sub(0, 0); /* Comparison in while */ + st_fx->ac_range_fx = UL_lshl_pos(st_fx->ac_range_fx, 8); + move32(); + + assert(st_fx->ac_range_fx < (1U << 24)); + + ac_enc_shift_fx(ptr, bp, st_fx); + } + + Dyn_Mem_Deluxe_Out(); +} + +static __forceinline Word16 ac_enc_finish_fx(UWord8 *ptr, Word16 *bp, Encoder_State_fx *st_fx) /* i/o: Encoder state */ +{ + Dyn_Mem_Deluxe_In(UWord32 val, mask, high; Word16 bits; UWord16 over1, over2;); + + /*bits = 24 - log2_i(st->ac_range); */ + bits = sub(norm_ul(st_fx->ac_range_fx), 7); + + mask = UL_lshr(0x00ffffff, bits); + + val = UL_addNs24(st_fx->ac_low_fx, mask, &over1); + high = UL_addNs24(st_fx->ac_low_fx, st_fx->ac_range_fx, &over2); + + L_xor(0, 0); /* For bit not */ + UL_and(1U, 1U); /* added counters */ + val = L_and(val, (~mask) & 0x00ffffff); + + L_xor(0, 0); /* For bit not */ + IF ((L_xor(over1, over2)) == 0) + { + L_sub(0, 0); /* For comparision in if */ + IF (UL_addNsD(val, mask) >= high) + { + bits = add(bits, 1); + mask = UL_lshr_pos(mask, 1); + val = UL_and(UL_addNsD(st_fx->ac_low_fx, mask), (~mask) & 0x00ffffff); + L_xor(0, 0); + UL_and(1, 1); /* For bit not , mask */ + } + + if (val < st_fx->ac_low_fx) + { + st_fx->ac_carry_fx = 1; + move16(); + } + } + + st_fx->ac_low_fx = val; + move32(); + + FOR (; bits > 0; bits -= 8) + { + ac_enc_shift_fx(ptr, bp, st_fx); + } + bits = add(bits, 8); + + assert(st_fx->ac_carry_fx == 0); + + IF (st_fx->ac_carry_count_fx > 0) + { + ptr[(*bp)++] = (UWord8)st_fx->ac_cache_fx; + move16(); + + FOR (; st_fx->ac_carry_count_fx > 1; st_fx->ac_carry_count_fx--) + { + ptr[(*bp)++] = 0xff; + move16(); + } + write_indice_forward(ptr, *bp, lshr(0xff, sub(8, bits)), bits); + } + ELSE + { + write_indice_forward(ptr, *bp, st_fx->ac_cache_fx, bits); + } + + Dyn_Mem_Deluxe_Out(); + return bits; +} + + +__forceinline Word16 read_bit(UWord8 *ptr, Word16 *bp, Word16 *mask) +{ + Dyn_Mem_Deluxe_In(Word16 bit;); + + bit = 0; + move16(); + if (s_and((Word16)ptr[*bp], *mask) > 0) + { + bit = 1; + move16(); + } + *mask = lshl_pos(*mask, 1); + move16(); + if (sub(*mask, 0x100) == 0) + { + *mask = 1; + move16(); + } + if (sub(*mask, 1) == 0) + { + *bp = sub(*bp, 1); + move16(); + } + + Dyn_Mem_Deluxe_Out(); + return bit; +} + + +static __forceinline void ac_dec_init_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_side, Word16 *mask_side, + Decoder_State_fx *st_fx) /* i/o: Decoder State */ +{ + Dyn_Mem_Deluxe_In(Counter i;); + + + st_fx->ac_low_fx = L_deposit_l(0); + move32(); + + st_fx->ac_range_fx = 0x00ffffff; + move32(); + FOR (i = 0; i < 3; i++) + { + if (check_pc_bytes(bp, bp_side, mask_side, 0, 1, &st_fx->pc) != 0) + { + Dyn_Mem_Deluxe_Out(); + return; + } + st_fx->ac_low_fx = UL_addNsD(UL_lshl_pos(st_fx->ac_low_fx, 8), UL_deposit_l((Word16)ptr[(*bp)++])); + move32(); + assert(st_fx->ac_low_fx < (1U << 24)); + } + + st_fx->BER_detect = 0; + move16(); + + Dyn_Mem_Deluxe_Out(); +} + +/* o : Decoded cumulative frequency */ +static __forceinline Word16 ac_decode_fx(Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 pki) +{ + Dyn_Mem_Deluxe_In(UWord16 sgn; Word16 val, r;); + + st_fx->ac_help_fx = UL_lshr_pos(st_fx->ac_range_fx, 10); + move32(); + val = 0; + move16(); + + r = add(val, 8); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ari_spec_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 4); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ari_spec_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 2); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ari_spec_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 1); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ari_spec_cumfreq[pki][r]), &sgn); + IF (sgn == 0) + { + val = r; + move16(); + IF (sub(val, 15) == 0) + { + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ari_spec_cumfreq[pki][16]), &sgn); + if (sgn == 0) + { + val = 16; + move16(); + } + UL_subNs(st_fx->ac_low_fx, UL_lshl(st_fx->ac_help_fx, 10), &sgn); + if (sgn == 0) + { + st_fx->BER_detect = 1; + move16(); + } + } + } + + Dyn_Mem_Deluxe_Out(); + return val; +} + +/* o : Decoded cumulative frequency */ +static __forceinline Word16 ac_decode_tns_order(Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 enable_lpc_weighting) +{ + Dyn_Mem_Deluxe_In(UWord16 sgn; Word16 val, r;); + + st_fx->ac_help_fx = UL_lshr_pos(st_fx->ac_range_fx, 10); + move32(); + val = 0; + move16(); + + r = add(val, 4); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_order_cumfreq[enable_lpc_weighting][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 2); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_order_cumfreq[enable_lpc_weighting][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 1); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_order_cumfreq[enable_lpc_weighting][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + UL_subNs(st_fx->ac_low_fx, UL_lshl(st_fx->ac_help_fx, 10), &sgn); + if (sgn == 0) + { + st_fx->BER_detect = 1; + move16(); + } + + Dyn_Mem_Deluxe_Out(); + return val; +} + +/* o : Decoded cumulative frequency */ +static __forceinline Word16 ac_decode_tns_coef(Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 pki) +{ + Dyn_Mem_Deluxe_In(UWord16 sgn; Word16 val, r;); + + st_fx->ac_help_fx = UL_lshr_pos(st_fx->ac_range_fx, 10); + move32(); + val = 0; + move16(); + + r = add(val, 8); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_coef_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 4); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_coef_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 2); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_coef_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + } + + r = add(val, 1); + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_coef_cumfreq[pki][r]), &sgn); + if (sgn == 0) + { + val = r; + move16(); + IF (sub(val, 15) == 0) + { + UL_subNs(st_fx->ac_low_fx, UL_Mpy_32_32(st_fx->ac_help_fx, ac_tns_coef_cumfreq[pki][16]), &sgn); + if (sgn == 0) + { + val = 16; + move16(); + } + UL_subNs(st_fx->ac_low_fx, UL_lshl(st_fx->ac_help_fx, 10), &sgn); + if (sgn == 0) + { + st_fx->BER_detect = 1; + move16(); + } + } + } + + Dyn_Mem_Deluxe_Out(); + return val; +} + +static __forceinline Word16 ac_dec_update_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_side, Word16 *mask_side, + Word16 cur_bin, Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 cum_freq, /* i : Cumulative frequency */ + UWord32 sym_freq /* i : Symbol frequency */ +) +{ + UWord32 UL_tmp; + + + assert(st_fx->ac_help_fx < (1U << 24)); + assert(cum_freq < (1U << 24)); + + UL_tmp = UL_Mpy_32_32(cum_freq, st_fx->ac_help_fx); + assert(UL_tmp < (1U << 24)); + + st_fx->ac_low_fx = UL_subNsD(st_fx->ac_low_fx, UL_tmp); + move32(); /*0+0*/ + assert(st_fx->ac_low_fx < (1U << 24)); + + st_fx->ac_range_fx = UL_Mpy_32_32(st_fx->ac_help_fx, sym_freq); + move32(); + + assert(st_fx->ac_range_fx < (1U << 24)); + /* updated to 16 from 24 */ + WHILE (st_fx->ac_range_fx < (1U << 16)) + { + L_sub(0, 0); /* For comparision in while*/ + + st_fx->ac_low_fx = + UL_and(st_fx->ac_low_fx, 0x0000ffFF); /* make sure upshift doe not lead to more than 24 bits */ + assert(st_fx->ac_low_fx < 1U << 16); + + if (check_pc_bytes(bp, bp_side, mask_side, cur_bin, 1, &st_fx->pc) != 0) + return 1; + + /*shift in 8 bits */ + st_fx->ac_low_fx = UL_addNsD(UL_lshl_pos(st_fx->ac_low_fx, 8), UL_deposit_l((Word16)ptr[(*bp)++])); + move32(); + + assert(st_fx->ac_low_fx < (1U << 24)); + st_fx->ac_range_fx = UL_lshl_pos(st_fx->ac_range_fx, 8); + move32(); + assert(st_fx->ac_range_fx < (1U << 24)); + } + return 0; +} + +static __forceinline void pc_init_fx(Word16 n_pc, Word16 numbytes, Word16 be_bp_left, Word16 be_bp_right, Word16 L_spec, + Word16 enc, Word16 sim_dec, Word16 bfi, Pc_State_fx *pc /* i/o: Pc State */ +) +{ +pc->inv_bin = add(L_spec, 1); move16(); +pc->numbytes = numbytes; move16(); +pc->c_bp = 0; move16(); +pc->c_bp_side = 0; move16(); +pc->bytes = shr(add(n_pc, 1),1); move16(); +pc->b_left = add(numbytes,1); move16(); +pc->b_right = -1; move16(); +pc->enc = enc; move16(); +pc->sim_dec = sim_dec; move16(); +pc->bfi = bfi; move16(); +pc->be_bp_left = shr(be_bp_left, 3); move16(); +pc->be_bp_right = shr(be_bp_right, 3); move16(); + assert(pc->be_bp_right < pc->bytes || pc->bytes == 0); +} + +static __forceinline Word16 check_pc_bytes(Word16 *bp, Word16 *bp_side, Word16 *mask_side, Word16 cur_bin, + Word16 from_left, Pc_State_fx *pc /* i/o: Pc State */) +{ + Dyn_Mem_Deluxe_In(Word16 bp_local, bp_side_local, offset;); + + IF (pc->bytes > 0) + { + test(); + IF (from_left == 0 && sub(*mask_side, 1) != 0) + { + Dyn_Mem_Deluxe_Out(); + return 0; + } + test(); + IF (pc->c_bp_side > 0 && *bp_side < 0) + { + assert(*mask_side == 1); + assert(pc->b_right != -1); + *bp_side = pc->b_right; + Dyn_Mem_Deluxe_Out(); + return 0; + } + bp_local = *bp; + bp_side_local = *bp_side; + + IF (from_left != 0) + { + if (sub(*mask_side, 1) == 0) + { + bp_side_local = add(bp_side_local, 1); + } + } + ELSE + { + bp_local = sub(bp_local, 1); + } + + IF (pc->b_right < 0) + { + offset = -1; + move16(); + if (pc->enc == 0) + { + offset = add(offset, pc->bytes); + } + + IF (add(bp_side_local, sub(offset, bp_local)) == pc->bytes) + { + pc->b_left = add(bp_local, 1); + pc->b_right = sub(bp_side_local, 1); + IF (pc->enc != 0) + { + assert(pc->b_right - pc->b_left + 1 == pc->bytes); + Dyn_Mem_Deluxe_Out(); + return 1; + } + } + } + + test(); + IF (pc->enc == 0 && pc->b_right >= 0) + { + test(); + IF (from_left != 0 && sub(*bp, pc->b_left) == 0) + { + IF (pc->sim_dec == 1) + { + pc->b_left = *bp; + Dyn_Mem_Deluxe_Out(); + return 1; + } + *bp = 0; move16(); + pc->c_bp = 1; move16(); + } + test(); + IF (from_left == 0 && sub(bp_side_local, pc->b_right) == 0) + { + *bp_side = sub(pc->bytes, 1); + move16(); + pc->c_bp_side = 1; + move16(); + } + IF (sub(pc->bfi, 2) == 0) + { + test(); + test(); + IF ((pc->c_bp != 0 && sub(*bp, pc->be_bp_left) >= 0) || + (pc->c_bp_side != 0 && sub(*bp_side, pc->be_bp_right) <= 0)) + { + pc->inv_bin = cur_bin; + move16(); + Dyn_Mem_Deluxe_Out(); + return 1; + } + ELSE IF ((pc->c_bp != 0 && *bp >= 0) || (pc->c_bp_side != 0 && sub(*bp_side, sub(pc->bytes, 1)) <= 0)) + { + pc->inv_bin = s_min(pc->inv_bin, cur_bin); + Dyn_Mem_Deluxe_Out(); + return 0; + } + } + } + } + + Dyn_Mem_Deluxe_Out(); + return 0; +} + diff --git a/lib_lc3plus/attack_detector_fx.c b/lib_lc3plus/attack_detector_fx.c new file mode 100644 index 000000000..3c62f8494 --- /dev/null +++ b/lib_lc3plus/attack_detector_fx.c @@ -0,0 +1,119 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void attack_detector_fx(LC3PLUS_Enc *enc, EncSetup *setup, Word16 *input, Word16 input_scaling, void *scratch) +{ + Dyn_Mem_Deluxe_In( + int i, j, position; + Word32 tmp, *block_energy; + Word16 h16, l16, new_scaling, rescale, input_delta_scaling; + Word16 scales[3], *input_16k; + Word16 frame_length_16k; + ); + + block_energy = scratchAlign(scratch, 0); + input_16k = scratchAlign(block_energy, 4 * 4 + 4); + frame_length_16k = DEPR_i_mult(enc->attdec_nblocks, 40); + + IF (setup->attack_handling) + { + /* input scaling */ + scales[0] = add(getScaleFactor16(input, enc->frame_length), input_scaling); + scales[1] = add(getScaleFactor16_0(setup->attdec_filter_mem, 2), setup->attdec_scaling); + scales[2] = + shr(add(add(getScaleFactor32_0(&setup->attdec_acc_energy, 1), shl(setup->attdec_scaling, 1)), 1), 1); + new_scaling = s_min(scales[0], s_min(scales[1], scales[2])); + + new_scaling = sub(new_scaling, 2); /* add overhead for resampler*/ + + /* memory re-scaling */ + rescale = sub(new_scaling, setup->attdec_scaling); + + IF (rescale) + { + rescale = s_min(s_max(rescale, -15), 15); + setup->attdec_filter_mem[0] = shl(setup->attdec_filter_mem[0], rescale); move16(); + setup->attdec_filter_mem[1] = shl(setup->attdec_filter_mem[1], rescale); move16(); + setup->attdec_acc_energy = L_shl(setup->attdec_acc_energy, shl(rescale, 1)); move16(); + } + setup->attdec_scaling = new_scaling; move16(); + + SWITCH (enc->fs) + { + case 32000: + input_delta_scaling = sub(1, sub(new_scaling, input_scaling)); + FOR (i = 0; i < frame_length_16k; i++) + { + input_16k[i] = add(shr(input[2 * i + 0], input_delta_scaling), + shr(input[2 * i + 1], input_delta_scaling)); move16(); + } + break; + case 48000: + input_delta_scaling = sub(2, sub(new_scaling, input_scaling)); + FOR (i = 0; i < frame_length_16k; i++) + { + input_16k[i] = add(shr(input[3 * i + 0], input_delta_scaling), + add(shr(input[3 * i + 1], input_delta_scaling), + shr(input[3 * i + 2], input_delta_scaling))); move16(); + } + break; + default: ASSERT(!"sampling rate not supported in function attack_detector_fx!"); break; + } + + input_16k[-2] = setup->attdec_filter_mem[0]; move16(); + input_16k[-1] = setup->attdec_filter_mem[1]; move16(); + setup->attdec_filter_mem[0] = input_16k[frame_length_16k - 2]; move16(); + setup->attdec_filter_mem[1] = input_16k[frame_length_16k - 1]; move16(); + + FOR (i = frame_length_16k - 1; i >= 0; i--) + { + tmp = L_mult(input_16k[i], 12288); + tmp = L_msu(tmp, input_16k[i - 1], 16384); + tmp = L_mac(tmp, input_16k[i - 2], 4096); + + input_16k[i] = extract_h(tmp); move16(); + } + + basop_memset(block_energy, 0, 4 * sizeof(Word32)); + + FOR (j = 0; j < enc->attdec_nblocks; j++) + { + FOR (i = 0; i < 40; i++) + { + block_energy[j] = L_mac(block_energy[j], input_16k[i + j*40], input_16k[i + j*40]); move16(); + } + } + + setup->attdec_detected = setup->attdec_position >= enc->attdec_hangover_thresh; + test(); move16(); + position = -1; move16(); + + FOR (i = 0; i < enc->attdec_nblocks; i++) + { + /* block_energy[i] / 8.5 */ + l16 = extract_l(L_shr(block_energy[i], 1)); + l16 = s_and(l16, 0x7fff); + h16 = extract_h(block_energy[i]); + tmp = L_shr(L_mult0(l16, 30840), 15); + tmp = L_shr(L_mac0(tmp, h16, 30840), 2); + + IF (tmp > setup->attdec_acc_energy) + { + position = i; move16(); + setup->attdec_detected = 1; move16(); + } + setup->attdec_acc_energy = L_max(L_shr(setup->attdec_acc_energy, 2), block_energy[i]); move16(); + } + setup->attdec_position = position; move16(); + } + + Dyn_Mem_Deluxe_Out(); +} diff --git a/lib_lc3plus/basop_mpy_lc3plus.c b/lib_lc3plus/basop_mpy_lc3plus.c new file mode 100644 index 000000000..88a6d336b --- /dev/null +++ b/lib_lc3plus/basop_mpy_lc3plus.c @@ -0,0 +1,99 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" + +#include "functions.h" + +#ifdef ENABLE_HR_MODE +Word32 Mpy_32_32_0(Word32 x, Word32 y) +{ + Word32 z; + + z = L_shr(L_add(Mpy_32_32_lc3plus(x, y),1), 1); + + return (z); +} + +Word32 Mpy_32_16_0(Word32 x, Word16 y) +{ + Word32 z; + + z = L_shr(L_add(Mpy_32_16_lc3plus(x, y),1), 1); + + return (z); +} +#endif + +Word32 Mpy_32_16_lc3plus(Word32 x, Word16 y) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss(x, y, &mh, &ml); + + return (mh); +} + + +Word32 Mpy_32_32_lc3plus(Word32 x, Word32 y) +{ + Word32 mh; + UWord32 ml; + + Mpy_32_32_ss(x, y, &mh, &ml); + + return (mh); +} + + +void cplxMpy_32_16(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a_Im, const Word16 b_Re, + const Word16 b_Im) +{ + *c_Re = L_sub(Mpy_32_16_lc3plus(a_Re, b_Re), Mpy_32_16_lc3plus(a_Im, b_Im)); move32(); + *c_Im = L_add(Mpy_32_16_lc3plus(a_Re, b_Im), Mpy_32_16_lc3plus(a_Im, b_Re)); move32(); +} + +void cplxMpy_32_32(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a_Im, const Word32 b_Re, + const Word32 b_Im) +{ + *c_Re = L_sub(Mpy_32_32_lc3plus(a_Re, b_Re), Mpy_32_32_lc3plus(a_Im, b_Im)); move32(); + *c_Im = L_add(Mpy_32_32_lc3plus(a_Re, b_Im), Mpy_32_32_lc3plus(a_Im, b_Re)); move32(); +} + +#ifdef ENABLE_HR_MODE +Word32 Mac_32_16_0(Word32 z, Word32 x, Word16 y) +{ + z = L_add(z, Mpy_32_16_0(x, y)); + + return (z); +} + +Word32 Mac_32_32_0(Word32 z, Word32 x, Word32 y) +{ + z = L_add(z, Mpy_32_32_0(x, y)); + + return (z); +} + +Word32 Msu_32_16_0(Word32 z, Word32 x, Word16 y) +{ + z = L_sub(z, Mpy_32_16_0(x, y)); + + return (z); +} + +Word32 Msu_32_32_0(Word32 z, Word32 x, Word32 y) +{ + z = L_sub(z, Mpy_32_32_0(x, y)); + + return (z); +} + +#endif /* #ifdef ENABLE_HR_MODE */ diff --git a/lib_lc3plus/basop_mpy_lc3plus.h b/lib_lc3plus/basop_mpy_lc3plus.h new file mode 100644 index 000000000..7c08755ee --- /dev/null +++ b/lib_lc3plus/basop_mpy_lc3plus.h @@ -0,0 +1,94 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" + +#ifndef __BASOP_MPY_H +#define __BASOP_MPY_H + +#include "functions.h" + +#ifdef ENABLE_HR_MODE +Word32 Mpy_32_16_0(Word32 x, Word16 y); +#endif + +Word32 Mac_32_16_0(Word32 z, Word32 x, Word16 y); +Word32 Mpy_32_32_0(Word32 x, Word32 y); +Word32 Mac_32_32_0(Word32 z, Word32 x, Word32 y); +Word32 Msu_32_16_0(Word32 z, Word32 x, Word16 y); +Word32 Msu_32_32_0(Word32 z, Word32 x, Word32 y); + +/** + * \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_lc3plus(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_lc3plus(Word32 x, Word32 y); + +#ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + +# ifdef ENABLE_HR_MODE +# define cplxMpy32_32_32_2(re, im, a, b, c, d) \ + do \ + { \ + re = L_sub(Mpy_32_32_0(a, c), Mpy_32_32_0(b, d)); \ + im = L_add(Mpy_32_32_0(a, d), Mpy_32_32_0(b, c)); \ + } while (0) +# endif +# define cplxMpy32_32_16_2(re, im, a, b, c, d) \ + do \ + { \ + re = L_sub(L_shr_pos(Mpy_32_16_lc3plus(a, c), 1), L_shr_pos(Mpy_32_16_lc3plus(b, d), 1)); \ + im = L_add(L_shr_pos(Mpy_32_16_lc3plus(a, d), 1), L_shr_pos(Mpy_32_16_lc3plus(b, c), 1)); \ + } while (0) + + +#else /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + +# ifdef ENABLE_HR_MODE +# define cplxMpy32_32_32_2(re, im, a, b, c, d) \ + do \ + { \ + re = L_sub(Mpy_32_32_0(a, c), Mpy_32_32_0(b, d)); \ + im = L_add(Mpy_32_32_0(a, d), Mpy_32_32_0(b, c)); \ + } while (0) +# endif +# define cplxMpy32_32_16_2(re, im, a, b, c, d) \ + do \ + { \ + re = L_sub(L_shr_pos(Mpy_32_16_lc3plus(a, c), 1), L_shr_pos(Mpy_32_16_lc3plus(b, d), 1)); \ + im = L_add(L_shr_pos(Mpy_32_16_lc3plus(a, d), 1), L_shr_pos(Mpy_32_16_lc3plus(b, c), 1)); \ + } while (0) + +#endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + +void cplxMpy_32_16(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a_Im, const Word16 b_Re, + const Word16 b_Im); +void cplxMpy_32_32(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a_Im, const Word32 b_Re, + const Word32 b_Im); + +#endif /* __BASOP_SETTINGS_H */ diff --git a/lib_lc3plus/basop_util_lc3plus.c b/lib_lc3plus/basop_util_lc3plus.c new file mode 100644 index 000000000..55a9b9eb1 --- /dev/null +++ b/lib_lc3plus/basop_util_lc3plus.c @@ -0,0 +1,1069 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" +#include "rom_basop_util.h" +#include "basop_util_lc3plus.h" + +extern const Word32 SqrtTable_lc3plus[32]; +extern const Word16 SqrtDiffTable_lc3plus[32]; + +extern const Word32 ISqrtTable_lc3plus[32]; +extern const Word16 ISqrtDiffTable_lc3plus[32]; + +extern const Word32 InvTable_lc3plus[32]; +extern const Word16 InvDiffTable_lc3plus[32]; + +Word32 BASOP_Util_Log2_lc3plus(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_lc3plus[0]); /* nIn^i * coeff[0] */ + accuSqr = mult(nIn, nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 2 */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[1]); /* nIn^i * coeff[1] */ + accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 3 */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[2]); /* nIn^i * coeff[2] */ + accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 4 */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[3]); /* nIn^i * coeff[3] */ + accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 5 */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[4]); /* nIn^i * coeff[4] */ + accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 6 */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[5]); /* nIn^i * coeff[5] */ + accuSqr = mult(accuSqr, nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 7, no need to calculate accuSqr any more */ + accuRes = L_mac(accuRes, accuSqr, ldCoeff_lc3plus[6]); /* nIn^i * coeff[6] */ + + /* 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_lc3plus(Word32 x) +{ +#ifdef ENABLE_HR_MODE + /* Original code was used for negative x and hence the exp was always 0, which is assumed */ + Word16 exp; + return BASOP_Util_InvLog2_pos(x, &exp); +#else + Word16 frac; + Word16 exp; + Word32 retVal; + UWord32 index3; + UWord32 index2; + UWord32 index1; + UWord32 lookup3f; + UWord32 lookup12; + UWord32 lookup; + + if (x < -1040187392l /*-31.0/64.0 Q31*/) + { + + return 0; + } + test(); + if ((L_sub(x, 1040187392l /*31.0/64.0 Q31*/) >= 0) || (x == 0)) + { + + return 0x7FFFFFFF; + } + + frac = extract_l(L_and(x, 0x3FF)); + + index3 = L_and(L_shr_pos(x, 10), 0x1F); + index2 = L_and(L_shr_pos(x, 15), 0x1F); + index1 = L_and(L_shr_pos(x, 20), 0x1F); + + exp = extract_l(L_shr_pos(x, 25)); + if (x > 0) + { + exp = sub(31, exp); + } + if (x < 0) + { + exp = negate(exp); + } + + lookup3f = L_add(exp2x_tab_long_lc3plus[index3], L_shr_pos(Mpy_32_16_lc3plus(0x0016302F, frac), 1)); + lookup12 = Mpy_32_32_lc3plus(exp2_tab_long_lc3plus[index1], exp2w_tab_long_lc3plus[index2]); + lookup = Mpy_32_32_lc3plus(lookup12, lookup3f); + + retVal = L_shr(lookup, sub(exp, 3)); + + return retVal; +#endif +} + +#ifdef ENABLE_HR_MODE +/* New function which works with positive and negative exponents */ +Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp) +{ + Word16 frac; + Word16 ret_exp; + Word32 retVal; + UWord32 index3; + UWord32 index2; + UWord32 index1; + UWord32 lookup3f; + UWord32 lookup12; + UWord32 lookup; + + /* The usage of exp.mantissa format in LC3plus in Word32 is : floatval = mantissa / (2^(31 - exp)) */ + ret_exp = extract_l(L_shr(x, 25)); + + IF (x < -1040187392l /*-31.0/64.0 Q31*/) + { + *exp = 0; + move16(); + return 0; + } + test(); + IF ((L_sub(x, 1040187392l /*31.0/64.0 Q31*/) >= 0)) + { + *exp = 31; + move16(); + return 0x40000000; + } + ELSE IF(x == 0) + { + *exp = -1; + move16(); + return 0x10000000; + } + + 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); + + lookup3f = L_add(exp2x_tab_long_lc3plus[index3], L_shr(Mpy_32_16_lc3plus(0x0016302F, frac), 1)); + lookup12 = Mpy_32_32_lc3plus(exp2_tab_long_lc3plus[index1], exp2w_tab_long_lc3plus[index2]); + lookup = Mpy_32_32_lc3plus(lookup12, lookup3f); + + IF (x > 0) + { + /* The returned exponent is the offset from 31, so the float result is + retVal / 2^(31 - *exp) */ + *exp = add(ret_exp, 3); + retVal = lookup; + } + ELSE + { + /* For negative powers provide the result in Q31 and ignore the exponent */ + *exp = 0; + retVal = L_shr(lookup, sub(negate(ret_exp), 3)); + } + + return retVal; +} +#endif + +/* local function for Sqrt16_lc3plus and Sqrt16norm */ +static Word16 Sqrt16_common(Word16 m, Word16 e) +{ + Word16 index, frac; + + assert((m >= 0x4000) || (m == 0)); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(m, 0x1FF); /* Q9 */ + + /* interpolate */ + if (m != 0) + { + m = mac_r(SqrtTable_lc3plus[index], SqrtDiffTable_lc3plus[index], frac); + } + + /* handle odd exponents */ + if (s_and(e, 1) != 0) + m = mult_r(m, 0x5a82); + + return m; +} + +/* local function for ISqrt16 and ISqrt16norm */ +static Word16 ISqrt16_common(Word16 m, Word16 e) +{ + Word16 index, frac; + + assert(m >= 0x4000); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(m, 0x1FF); /* Q9 */ + + /* interpolate */ + m = msu_r(ISqrtTable_lc3plus[index], ISqrtDiffTable_lc3plus[index], frac); + + /* handle even exponents */ + if (s_and(e, 1) == 0) + m = mult_r(m, 0x5a82); + + return m; +} + +Word16 Sqrt16_lc3plus( /*!< 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 ISqrt16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 preShift, e; + + assert(mantissa > 0); + + /* normalize */ + preShift = norm_s(mantissa); + + e = sub(*exponent, preShift); + mantissa = shl(mantissa, preShift); + + /* calc mantissa */ + mantissa = ISqrt16_common(mantissa, e); + + /* e = (2 - e) >> 1 */ + *exponent = msu_r(1L << 15, e, 1 << 14); move16(); + + return mantissa; +} + +Word16 Inv16_lc3plus( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 index, frac; + Word16 preShift; + Word16 m, e; + + assert(mantissa != 0); + + /* absolute */ + m = abs_s(s_max(mantissa, MIN_16 + 1)); + + /* 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_lc3plus[index], InvDiffTable_lc3plus[index], frac); + + /* restore sign */ + if (mantissa < 0) + m = negate(m); + + /* e = 1 - e */ + *exponent = sub(1, e); move16(); + + return m; +} + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word16 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x
+ and -32768 <= x <= -16384 for negative x +*/ + +Word16 getScaleFactor16( /* o: measured headroom in range [0..15], 0 if all x[i] == 0 */ + const Word16 *x, /* i: array containing 16-bit data */ + const Word16 len_x) /* i: length of the array to scan */ +{ + Counter i; + Word16 i_min, i_max; + Word16 x_min, x_max; + + x_max = 0; move16(); + x_min = 0; move16(); + FOR (i = 0; i < len_x; i++) + { + if (x[i] >= 0) + x_max = s_max(x_max, x[i]); + if (x[i] < 0) + x_min = s_min(x_min, x[i]); + } + + i_max = 0x10; move16(); + i_min = 0x10; move16(); + + if (x_max != 0) + i_max = norm_s(x_max); + + if (x_min != 0) + i_min = norm_s(x_min); + + i = s_and(s_min(i_max, i_min), 0xF); + + return i; +} + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word16 input array is returned
+ If the input array contains only '0', a scalefactor 16 is returned
+ Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x
+ and -32768 <= x <= -16384 for negative x +*/ + +Word16 getScaleFactor16_0( /* o: measured headroom in range [0..15], 16 if all x[i] == 0 */ + const Word16 *x, /* i: array containing 16-bit data */ + const Word16 len_x) /* i: length of the array to scan */ +{ + Counter i; + Word16 i_min, i_max; + Word16 x_min, x_max; + + x_max = 0; move16(); + x_min = 0; move16(); + FOR (i = 0; i < len_x; i++) + { + if (x[i] >= 0) + x_max = s_max(x_max, x[i]); + if (x[i] < 0) + x_min = s_min(x_min, x[i]); + } + + i_max = 0x10; move16(); + i_min = 0x10; move16(); + + if (x_max != 0) + i_max = norm_s(x_max); + + if (x_min != 0) + i_min = norm_s(x_min); + + i = s_min(i_max, i_min); + + return i; +} + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x +*/ + +Word16 getScaleFactor32_lc3plus( /* 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 */ +{ + Counter i; + Word16 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; +} + +/********************************************************************/ +/*! + \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 32 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_0( /* o: measured headroom in range [0..31], 32 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 */ +{ + Counter i; + Word16 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_min(i_max, i_min); + + return i; +} + +Word16 BASOP_Util_Divide3216_Scale_lc3plus( /* 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 */ + x = L_abs(L_max(x, MIN_32 + 1)); + y = abs_s(s_max(y, MIN_16 + 1)); + sx = sub(norm_l(x), 1); + x = L_shl(x, sx); + sy = norm_s(y); + y = shl(y, sy); + *s = sub(sy, sx); move16(); + + z = div_s(round_fx(x), y); + + if (sign < 0) /* if sign bits differ, negate the result */ + { + z = negate(z); + } + + return z; +} + +Word16 BASOP_Util_Divide1616_Scale_lc3plus(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) + { + *s = 0; move16(); + + return ((Word16)0); + } + + sx = norm_s(x); + x = shl(x, sx); + x = shr(x, 1); + *s = sub(1, sx); move16(); + + sy = norm_s(y); + y = shl(y, sy); + *s = add(*s, sy); move16(); + + z = div_s(x, y); + + if (sign != 0) + { + z = negate(z); + } + + return z; +} + +Word32 Norm32Norm(const Word32 *x, const Word16 headroom, const Word16 length, Word16 *result_e) +{ + Word32 L_tmp, L_tmp2, inc; + Word16 s, shift, tmp; + Counter i; + + shift = headroom; move16(); + + L_tmp = L_deposit_l(0); + + FOR (i = 0; i < length; i++) + { + L_tmp2 = L_sub(L_tmp, 0x40000000); + if (L_tmp2 >= 0) + shift = sub(shift, 1); + if (L_tmp2 >= 0) + L_tmp = L_shr(L_tmp, 2); + + tmp = round_fx_sat(L_shl_sat(x[i], shift)); + L_tmp = L_mac0(L_tmp, tmp, tmp); /* exponent = (1-shift*2) , Q(30+shift*2) */ + } + + /* Consider an increase of 0xfffd per sample in case that the pre-shift factor + in the acf is 1 bit higher than the shift factor estimated in this function. + This prevent overflows in the acf. */ + IF (L_tmp != 0) + { + s = norm_s(length); + inc = L_shl(Mpy_32_16_lc3plus(0x0000fffd, shl(length, s)), sub(15, s)); + L_tmp = L_add_sat(L_tmp, inc); + } + + *result_e = sub(1, shl(shift, 1)); move16(); + + return L_tmp; +} + +void Scale_sig(Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Counter i; + Word16 tmp; + IF (exp0 > 0) + { + tmp = s_min(exp0, 15); move16(); + FOR (i = 0; i < lg; i++) + { + x[i] = shl(x[i], tmp); move16(); /* saturation can occur here */ + } + return; + } + IF (exp0 < 0) + { + tmp = shl(-32768, s_max(exp0, -15)); /* we use negative to correctly represent 1.0 */ + FOR (i = 0; i < lg; i++) + { + x[i] = msu_r(0, x[i], tmp); move16(); /* msu instead of mac because factor is negative */ + } + return; + } +} + +void Copy_Scale_sig(const Word16 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Counter i; + Word16 tmp; + + IF (exp0 == 0) + { + basop_memmove(y, x, lg * sizeof(Word16)); + + return; + } + IF (exp0 < 0) + { + tmp = shl(-32768, exp0); /* we use negative to correctly represent 1.0 */ + FOR (i = 0; i < lg; i++) + { + y[i] = msu_r(0, x[i], tmp); move16(); + } + return; + } + FOR (i = 0; i < lg; i++) + { + y[i] = shl_sat(x[i], exp0); move16(); /* saturation can occur here */ + } +} + +Word32 BASOP_Util_Add_Mant32Exp_lc3plus /*!< 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); +} + +Word16 BASOP_Util_Cmp_Mant32Exp_lc3plus /*!< o: flag: result of comparison */ + /* 0, if a == b */ + /* 1, if a > b */ + /* -1, if a < b */ + (Word32 a_m, /*!< i: Mantissa of 1st operand a */ + Word16 a_e, /*!< i: Exponent of 1st operand a */ + Word32 b_m, /*!< i: Mantissa of 2nd operand b */ + Word16 b_e) /*!< i: Exponent of 2nd operand b */ + +{ + Word32 diff_m; + Word16 diff_e, shift, result; + + /* + This function compares two input parameters, both represented by a 32-bit mantissa and a 16-bit exponent. + If both values are identical, 0 is returned. + If a is greater b, 1 is returned. + If a is less than b, -1 is returned. + */ + + /* Check, if both mantissa and exponents are identical, when normalized: return 0 */ + shift = norm_l(a_m); + if (shift) + a_m = L_shl(a_m, shift); + if (shift) + a_e = sub(a_e, shift); + + shift = norm_l(b_m); + if (shift) + b_m = L_shl(b_m, shift); + if (shift) + b_e = sub(b_e, shift); + + /* align exponent, if any mantissa is zero */ + if (!a_m) + a_e = add(b_e, 0); + if (!b_m) + b_e = add(a_e, 0); + + IF (a_m > 0 && b_m < 0) + { + diff_m = 1; move16(); + } + ELSE IF (a_m<0 && b_m> 0) + { + diff_m = -1; move16(); + } + ELSE + { + diff_m = L_sub(a_m, b_m); + } + + diff_e = sub(a_e, b_e); + + test(); + IF (diff_m == 0 && diff_e == 0) + { + return 0; + } + + /* Check sign, exponent and mantissa to identify, whether a is greater b or not */ + result = sub(0, 1); + + IF (a_m >= 0) + { + /* a is positive */ + if (b_m < 0) + { + result = add(1, 0); + } + + test(); test(); test(); + if ((b_m >= 0) && ((diff_e > 0) || (diff_e == 0 && diff_m > 0))) + { + result = add(1, 0); + } + } + ELSE + { + /* a is negative */ + test(); test(); test(); + if ((b_m < 0) && ((diff_e < 0) || (diff_e == 0 && diff_m > 0))) + { + result = add(1, 0); + } + } + return result; +} + +/*----------------------------------------------------------------------------------* + * Function: Isqrt + * + * Description: + * + * The function computes 1/sqrt(x). + * The mantissa of the input value must be in the range of 1.0 > x >= 0.5. + * The computation of the inverse square root is an approach with a lookup table + * and linear interpolation. + * + * result = x * 2^x_e + * + * Parameter: + * + * x [i] mantissa (Q31) + * x_e [i/o] pointer to exponent (Q0) + * + * Return value: + * + * mantissa (Q31) + * + *----------------------------------------------------------------------------------*/ +Word32 Isqrt(Word32 x, /* mantissa */ + Word16 *x_e /* pointer to exponent */ +) +{ + Word16 s; + Word32 y; + Word32 idx; + Word32 diff; + Word16 fract; + + IF (x <= 0) + { + *x_e = 0; move16(); + return 0x7FFFFFFF; + } + + /* check if exponent is odd */ + s = s_and(*x_e, 0x0001); + + /* get table index (upper 8 bits) */ + idx = L_and(L_shr(x, (31 - 8)), 0x00000007f); + + /* get fractional part for interpolation (lower 23 bits) */ + fract = extract_h(L_shl(L_and(x, 0x007FFFFF), 8)); + + /* interpolate */ + diff = L_sub(isqrt_table[idx + 1], isqrt_table[idx]); + y = L_add(isqrt_table[idx], Mpy_32_16_lc3plus(diff, fract)); + + /* if exponent is odd apply sqrt(0.5) */ + if (s != 0) + { + y = Mpy_32_16_lc3plus(y, 0x5A82 /*0x5A827999*/); + } + + /* if exponent is odd shift 1 bit left */ + if (s != 0) + { + y = L_shl(y, s); + } + + /* change sign, shift right and add 1 to exponent (implicit exponent of isqrt_table) */ + *x_e = mac_r(32768, *x_e, -16384); move16(); + + return y; +} + +Word16 BASOP_Util_Log2_16(Word32 x, Word16 x_e) +{ + Word16 shift, tmp1, tmp2; + Word16 outInt, outFrac, out; + + assert(x >= 0); + + if (x == 0) + { + return (MIN_16); + } + + /* Scale Input */ + shift = norm_l(x); + x = L_shl(x, sub(shift, 10)); + + /* Integer part */ + outInt = shl(sub(sub(x_e, shift), 1), 9); + + /* Fractional part */ + tmp1 = mac_r(x, -33, 16384); + tmp2 = lshr(extract_l(x), 6); + outFrac = mac_r(Log2_16_table1[tmp1], Log2_16_table2[tmp1], tmp2); + + /* Output */ + out = add(outInt, outFrac); + + return out; +} + +Word16 BASOP_Util_InvLog2_16(Word16 x, Word16 *y_e) +{ + Word16 tmp1, tmp2, y; + + tmp1 = shr(s_and(x, 2047), 5); + tmp2 = shl(s_and(x, 31), 4); + y = mac_r(InvLog2_16_table1[tmp1], InvLog2_16_table2[tmp1], tmp2); + *y_e = add(shr_pos(x, 11), 1); + + return y; +} + +#ifdef ENABLE_HR_MODE +#define DFRACT_BITS 32 /* double precision */ + +#define SQRT_BITS 7 +#define SQRT_BITS_MASK 0x7f +#define SQRT_FRACT_BITS_MASK 0x007FFFFF + +#ifndef Word64 +#define Word64 long long +#endif + +static __inline Word32 Mpy_32_32_noshift(Word32 x1, Word32 x2) +{ + Word64 ret = 0; + ret = ((Word64)x1 * (Word64)x2); + return ((Word32)((ret & (Word64)0xffffffff00000000) >> 32)); +} + +static __inline Word32 fixmadddiv2_DD(const Word32 x, const Word32 a, const Word32 b) +{ + return ((((Word64)x << 32) + (Word64)a * b) >> 32); +} + +/** + * \brief calculate 1.0/sqrt(op) + * \param op_m mantissa of input value. + * \param result_e pointer to return the exponent of the result + * \return mantissa of the result + */ +/***************************************************************************** + delivers 1/sqrt(op) normalized to .5...1 and the shift value of the OUTPUT, + i.e. the denormalized result is 1/sqrt(op) = invSqrtNorm(op) * 2^(shift) + uses Newton-iteration for approximation + Q(n+1) = Q(n) + Q(n) * (0.5 - 2 * V * Q(n)^2) + with Q = 0.5* V ^-0.5; 0.5 <= V < 1.0 +*****************************************************************************/ +static __inline Word32 invSqrtNorm2(Word32 op, Word32 *shift) +{ + Word32 val = op; + Word32 reg1, reg2; + + if (val == 0) + { + *shift = 16; + return ((Word32)0x7FFFFFFF); /* maximum positive value */ + } + +/* #define INVSQRTNORM2_NEWTON_ITERATE */ +#define INVSQRTNORM2_LINEAR_INTERPOLATE +#define INVSQRTNORM2_LINEAR_INTERPOLATE_HQ + + /* normalize input, calculate shift value */ + assert(val > 0); + *shift = norm_l(val); /* CountLeadingBits() is not necessary here since test value is always > 0 */ + val <<= *shift; /* normalized input V */ + *shift += 2; /* bias for exponent */ + +#if defined(INVSQRTNORM2_NEWTON_ITERATE) + /* Newton iteration of 1/sqrt(V) */ + reg1 = invSqrtTab[(Word32)(val >> (DFRACT_BITS - 1 - (SQRT_BITS + 1))) & SQRT_BITS_MASK]; + reg2 = FL2FXCONST_DBL(0.0625f); /* 0.5 >> 3 */ + + Word32 regtmp = fPow2Div2(reg1); /* a = Q^2 */ + regtmp = reg2 - fMultDiv2(regtmp, val); /* b = 0.5 - 2 * V * Q^2 */ + reg1 += (fMultDiv2(regtmp, reg1) << 4); /* Q = Q + Q*b */ +#elif defined(INVSQRTNORM2_LINEAR_INTERPOLATE) + Word32 index = (Word32)(val >> (DFRACT_BITS - 1 - (SQRT_BITS + 1))) & SQRT_BITS_MASK; + Word32 Fract = (Word32)(((Word32)val & SQRT_FRACT_BITS_MASK) << (SQRT_BITS + 1)); + Word32 diff = invSqrtTab[index + 1] - invSqrtTab[index]; + reg1 = invSqrtTab[index] + (Word32)(((UWord32)(Mpy_32_32_noshift(diff, Fract)) << 1)); +#if defined(INVSQRTNORM2_LINEAR_INTERPOLATE_HQ) + /* reg1 = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (Fract != (Word32)0) + { + /* fract = fract * (1 - fract) */ + Fract = Mpy_32_32_noshift(Fract, (Word32)((UWord32)0x80000000 - (Word32)Fract)) << 1; + diff = diff - (invSqrtTab[index + 2] - invSqrtTab[index + 1]); + reg1 = fixmadddiv2_DD(reg1, Fract, diff); + } +#endif /* INVSQRTNORM2_LINEAR_INTERPOLATE_HQ */ +#else +#error "Either define INVSQRTNORM2_NEWTON_ITERATE or INVSQRTNORM2_LINEAR_INTERPOLATE" +#endif + /* calculate the output exponent = input exp/2 */ + if (*shift & 0x00000001) + { /* odd shift values ? */ + /* Note: Do not use rounded value 0x5A82799A to avoid overflow with shift-by-2 */ + reg2 = (Word32)0x5A827999; /* FL2FXCONST_DBL(0.707106781186547524400844362104849f);*/ /* 1/sqrt(2); */ +#ifdef __ADSP21000__ + reg1 = fMult(reg1, reg2) << 1; /* compiler bug work around (CCES 2.4.0), and better precision */ +#else + reg1 = Mpy_32_32_noshift(reg1, reg2) << 2; +#endif + } + + *shift = *shift >> 1; + + return (reg1); +} + +/** + * \brief calculate 1.0/(op_m * 2^op_e) + * \param op_m mantissa of the input value. + * \param op_e pointer into were the exponent of the input value is stored, and the result will be stored into. + * \return mantissa of the result + */ +Word32 invFixp(Word32 op_m, Word16 *op_e) +{ + if ((op_m == (Word32)0x00000000) || (op_m == (Word32)0x00000001)) + { + *op_e = 31 - *op_e; + return ((Word32)0x7FFFFFFF); + } + + Word32 tmp_exp; + Word32 tmp_inv = invSqrtNorm2(op_m, &tmp_exp); + + *op_e = (tmp_exp << 1) - *op_e + 1; + return Mpy_32_32_noshift(tmp_inv, tmp_inv); +} +#endif diff --git a/lib_lc3plus/basop_util_lc3plus.h b/lib_lc3plus/basop_util_lc3plus.h new file mode 100644 index 000000000..99bc211a9 --- /dev/null +++ b/lib_lc3plus/basop_util_lc3plus.h @@ -0,0 +1,377 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef __BASOP_UTIL_LC3PLUS_H__ +#define __BASOP_UTIL_LC3PLUS_H__ + +#include "defines.h" +#include "functions.h" +#include +#include + +#define _LONG long +#define _SHORT short +#ifdef _WIN32 +#define _INT64 __int64 +#else +#define _INT64 long long +#endif + +#define WORD32_BITS 32 +#define MAXVAL_WORD32 ((signed)0x7FFFFFFF) +#define MINVAL_WORD32 ((signed)0x80000000) +#define WORD32_FIX_SCALE ((_INT64)(1) << (WORD32_BITS - 1)) + +#define WORD16_BITS 16 +#define MAXVAL_WORD16 (((signed)0x7FFFFFFF) >> 16) +#define MINVAL_WORD16 (((signed)0x80000000) >> 16) +#define WORD16_FIX_SCALE ((_INT64)(1) << (WORD16_BITS - 1)) + +/*! + \def Macro converts a Word32 fixed point to Word16 fixed point <1 with saturation +*/ +#define WORD322WORD16(val) \ + ((((((val) >> (WORD32_BITS - WORD16_BITS - 1)) + 1) > (((_LONG)1 << WORD16_BITS) - 1)) && ((_LONG)(val) > 0)) \ + ? (Word16)(_SHORT)(((_LONG)1 << (WORD16_BITS - 1)) - 1) \ + : (Word16)(_SHORT)((((val) >> (WORD32_BITS - WORD16_BITS - 1)) + 1) >> 1)) + + +/* Word16 Packed Type */ +typedef struct +{ + struct + { + Word16 re; + Word16 im; + } v; +} PWord16; + +#ifdef ENABLE_HR_MODE +/* Word32 Packed Type */ +typedef struct +{ + struct + { + Word32 re; + Word32 im; + } v; +} PWord32; +#endif + +#define cast16 move16 + +#define LD_DATA_SCALE (6) +#define LD_DATA_SHIFT_I5 (7) + +/************************************************************************/ +/*! + \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_lc3plus( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +Word16 ISqrt16( /*!< 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_lc3plus( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word16 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x
+ and -32768 <= x <= -16384 for negative x +*/ + +Word16 getScaleFactor16( /* o: measured headroom in range [0..15], 0 if all x[i] == 0 */ + const Word16 *x, /* i: array containing 16-bit data */ + const Word16 len_x); /* i: length of the array to scan */ + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word16 input array is returned
+ If the input array contains only '0', a scalefactor 16 is returned
+ Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x
+ and -32768 <= x <= -16384 for negative x +*/ + +Word16 getScaleFactor16_0( /* o: measured headroom in range [0..15], 16 if all x[i] == 0 */ + const Word16 *x, /* i: array containing 16-bit data */ + const Word16 len_x); /* i: length of the array to scan */ + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x +*/ + +Word16 getScaleFactor32_lc3plus( /* 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 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 32 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_0( /* o: measured headroom in range [0..31], 32 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 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_lc3plus(Word32 x, /*!< i : Numerator */ + Word16 y, /*!< i : Denominator*/ + Word16 *s); /*!< o : Additional scalefactor difference*/ + +/****************************************************************************/ +/*! + \brief Does fractional division of Word16 arg1 by Word16 arg2 + + + \return fractional Q15 Word16 z = arg1(Q15)/arg2(Q15) with scaling s +*/ +Word16 BASOP_Util_Divide1616_Scale_lc3plus(Word16 x, /*!< i : Numerator*/ + Word16 y, /*!< i : Denominator*/ + Word16 *s); /*!< o : Additional scalefactor difference*/ + +/************************************************************************/ +/*! + \brief Binary logarithm with 7 iterations + + \param x + + \return log2(x)/64 + */ +/************************************************************************/ +Word32 BASOP_Util_Log2_lc3plus(Word32 x); + +/************************************************************************/ +/*! + \brief Binary power + + Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen + + Version with 3 table lookup and 1 linear interpolations + + Algorithm: compute power of 2, argument x is in Q7.25 format + result = 2^(x/64) + We split exponent (x/64) into 5 components: + integer part: represented by b31..b25 (exp) + fractional part 1: represented by b24..b20 (lookup1) + fractional part 2: represented by b19..b15 (lookup2) + fractional part 3: represented by b14..b10 (lookup3) + fractional part 4: represented by b09..b00 (frac) + => result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp + + Due to the fact, that all lookup values contain a factor 0.5 + the result has to be shifted by 3 to the right also. + Table exp2_tab_long_lc3plus contains the log2 for 0 to 1.0 in steps + of 1/32, table exp2w_tab_long_lc3plus the log2 for 0 to 1/32 in steps + of 1/1024, table exp2x_tab_long_lc3plus the log2 for 0 to 1/1024 in + 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_lc3plus(Word32 x); + +#ifdef ENABLE_HR_MODE +/* New function which works with positive x, BASOP_Util_InvLog2_lc3plus does not give + accurate results for x > 0 */ +Word32 BASOP_Util_InvLog2_pos(Word32 x, Word16 *exp); +#endif + +/** + * \brief Compute dot product of 1 32 bit vectors with itself + * \param x input vector 1 + * \param headroom amount of headroom bits the input vector + * \param length the length of the input vector + * \param result_e pointer to where the exponent of the result will be stored into + * \return the dot product of x and x. + */ +Word32 Norm32Norm(const Word32 *x, const Word16 headroom, const Word16 length, Word16 *result_e); + +/*!********************************************************************** + \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_lc3plus /*!< o: normalized result mantissa */ + (Word32 a_m, /*!< i: Mantissa of 1st operand a */ + Word16 a_e, /*!< i: Exponent of 1st operand a */ + Word32 b_m, /*!< i: Mantissa of 2nd operand b */ + Word16 b_e, /*!< i: Exponent of 2nd operand b */ + Word16 *ptr_e); /*!< o: exponent of result */ + /*!********************************************************************** + \brief Returns the comparison result of two normalized values given by mantissa and exponent. + return value: -1: a < b, 0: a == b, 1; a > b + + Mantissas are in 32-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ + ************************************************************************/ +Word16 BASOP_Util_Cmp_Mant32Exp_lc3plus /*!< o: flag: result of comparison */ + (Word32 a_m, /*!< i: Mantissa of 1st operand a */ + Word16 a_e, /*!< i: Exponent of 1st operand a */ + Word32 b_m, /*!< i: Mantissa of 2nd operand b */ + Word16 b_e); /*!< i: Exponent of 2nd operand b */ + +/* compare two positive normalized 16 bit mantissa/exponent values */ +/* return value: positive if first value greater, negative if second value greater, zero if equal */ +Word16 compMantExp16Unorm(Word16 m1, Word16 e1, Word16 m2, Word16 e2); + +void Scale_sig(Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); +void Copy_Scale_sig(const Word16 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +#ifdef ENABLE_HR_MODE +void Copy_Scale_sig_32(const Word32 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); +#endif + +Word32 Isqrt(Word32 x, /* (i) Q31: normalized value (1.0 > x >= 0.5) */ + Word16 *x_e /* (i/o) Q0 : pointer to exponent */ +); + +Word16 BASOP_Util_Log2_16(Word32 x, Word16 x_e); + +Word16 BASOP_Util_InvLog2_16(Word16 x, Word16 *y_e); + +#ifdef ENABLE_HR_MODE +Word32 invFixp(Word32 op_m, Word16 *op_e); +#endif + +#define BASOP_CFFT_MAX_LENGTH 480 +void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 sizeOfFft, Word16 s, Word16 *scale, Word32 *x); +void BASOP_rfftN(Word32 *re, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer); +void BASOP_irfftN(Word32 *re, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer); + +#if WMOPS +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif + +static __inline void basop_memcpy(void *dst, const void *src, size_t n) +{ +#if WMOPS + multiCounter[currCounter].move16 += (UWord32)n / 2; +#endif + /* check for overlapping memory */ + assert((const char *)src + n <= (char *)dst || (char *)dst + n <= (const char *)src); + memcpy(dst, src, n); +} + +static __inline void basop_memmove(void *dst, const void *src, size_t n) +{ +#if WMOPS + multiCounter[currCounter].move16 += (UWord32)n / 2; +#endif + memmove(dst, src, n); +} + +static __inline void basop_memset(void *dst, int val, size_t n) +{ +#if WMOPS + multiCounter[currCounter].move16 += (UWord32)n / 2; +#endif + memset(dst, val, n); +} + +/* Macros around Dyn_Mem that don't require duplicate declarations. */ +#ifdef DYNMEM_COUNT +/* older visual studio doesn't have __func__ */ +#if defined _MSC_VER && _MSC_VER < 1900 +#define __func__ __FUNCTION__ +#endif +#define Dyn_Mem_Deluxe_In(...) __VA_ARGS__ Dyn_Mem_In(__func__, sizeof(struct {__VA_ARGS__})) +#define Dyn_Mem_Deluxe_Out() Dyn_Mem_Out() +#else +#define Dyn_Mem_Deluxe_In(...) __VA_ARGS__ +#define Dyn_Mem_Deluxe_Out() +#endif + +/* Macros missing from IVAS BASOP, used only in LC3plus */ +#define L_shl_pos(x, y) (L_shl((x), (y))) +#define L_shr_pos(x, y) (L_shr((x), (y))) +#define L_shr_pos_pos(x, y) (L_shr((x), (y))) + +#define L_shr_r_pos(x, shift) (L_shr_r(x, shift)) + +#define shl_pos(x, y) (shl((x), (y))) +#define shr_pos(x, y) (shr((x), (y))) +#define shr_pos_pos(x, y) (shr((x), (y))) + +#define lshl_pos(x, y) (lshl(x, y)) +#define UL_lshr_pos(x, y) (UL_lshr(x, y)) +#define UL_lshl_pos(x, y) (UL_lshl(x, y)) +#endif /* __BASOP_UTIL_LC3PLUS_H__ */ diff --git a/lib_lc3plus/constants.c b/lib_lc3plus/constants.c new file mode 100644 index 000000000..c13c4e49e --- /dev/null +++ b/lib_lc3plus/constants.c @@ -0,0 +1,5046 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "basop_util_lc3plus.h" +#include "constants.h" +#include "defines.h" + +#ifdef ENABLE_HR_MODE + +#ifdef CR8_G_ADD_75MS +const Word32 LowDelayShapes_n960_N480_HRA_7_5ms_IP[720] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 87, 348, 823, 1614, 2855, 4711, + 7394, 11166, 16346, 23325, 32567, 44630, 60168, 79951, 104871, + 135960, 174404, 221554, 278944, 348306, 431580, 530938, 648792, 787807, + 950923, 1141360, 1362631, 1618557, 1913273, 2251235, 2637225, 3076358, 3574079, + 4136163, 4768712, 5478142, 6271180, 7154844, 8136428, 9223482, 10423785, 11745317, + 13196231, 14784811, 16519438, 18408546, 20460576, 22683925, 25086898, 27677652, 30464139, + 33454048, 36654744, 40073208, 43715977, 47589078, 51697972, 56047490, 60641775, 65484225, + 70577443, 75923181, 81522294, 87374702, 93479345, 99834159, 106436041, 113280836, 120363317, + 127677184, 135215062, 142968508, 150928157, 159083617, 167423428, 175935264, 184605929, 193421420, + 202366999, 211427267, 220586253, 229827503, 239134176, 248489151, 257875132, 267274759, 276670727, + 286045896, 295383416, 304666842, 313880253, 323008369, 332036665, 340951481, 349740127, 358390986, + 366893607, 375238791, 383418672, 391426786, 399258131, 406909219, 414378115, 421664463, 428769507, + 435696092, 442448656, 449033209, 455457302, 461729975, 467861704, 473864325, 479750954, 485535888, + 491234502, 496863130, 502438943, 507979811, 513504165, 519030849, 524578969, 530167737, 535816319, + 541543674, 547368406, 553308608, 559381722, 565604392, 571992342, 578560249, 585321630, 592288748, + 599472521, 606882448, 614526549, 622411321, 630541701, 638921050, 647551149, 656432204, 665562870, + 674940281, 684560092, 694416534, 704502476, 714809492, 725327938, 736047035, 746954953, 758038900, + 769285219, 780679474, 792206554, 803850758, 815595897, 827425384, 839322323, 851269604, 863249984, + 875246176, 887240926, 899217093, 911157723, 923046119, 934865908, 946601106, 958236175, 969756079, + 981146337, 992393068, 1003483035, 1014403685, 1025143183, 1035690443, 1046035156, 1056167806, 1066079698, + 1075762962, 1085210568, 1094416328, 1103374896, 1112081767, 1120533266, 1128726537, 1136659525, 1144330955, + 1151740310, 1158887799, 1165774327, 1172401460, 1178771388, 1184886881, 1190751250, 1196368299, 1201742283, + 1206877859, 1211780040, 1216454151, 1220905777, 1225140726, 1229164983, 1232984668, 1236606003, 1240035271, + 1243278790, 1246342881, 1249233843, 1251957932, 1254521342, 1256930191, 1259190506, 1261308214, 1263289136, + 1265138979, 1266863333, 1268467669, 1269957337, 1271337562, 1272613448, 1273789972, 1274871989, 1275864224, + 1276771276, 1277597614, 1278347576, 1279025364, 1279635046, 1280180548, 1280665658, 1281094017, 1281469123, + 1281794327, 1282072831, 1282307692, 1282501820, 1282657982, 1282778803, 1282866770, 1282924240, 1282953439, + 1282956475, 1282935340, 1282891922, 1282828007, 1282745290, 1282645385, 1282529830, 1282400095, 1282257591, + 1282103675, 1281939658, 1281766811, 1281586369, 1281399536, 1281207489, 1281011380, 1280812338, 1280611471, + 1280409867, 1280208592, 1280008692, 1279811190, 1279617083, 1279427343, 1279242908, 1279064691, 1278893575, + 1278730391, 1278575934, 1278430953, 1278296152, 1278172183, 1278059646, 1277959085, 1277870984, 1277795766, + 1277733793, 1277685360, 1277650698, 1277629970, 1277623272, 1277630630, 1277652006, 1277687290, 1277736307, + 1277798815, 1277874509, 1277963018, 1278063911, 1278176696, 1278300826, 1278435697, 1278580655, 1278734998, + 1278897977, 1279068803, 1279246650, 1279430656, 1279619930, 1279813555, 1280010596, 1280210097, 1280411091, + 1280612606, 1280813664, 1281013290, 1281210515, 1281404382, 1281593947, 1281778291, 1281956514, 1282127749, + 1282291161, 1282445951, 1282591364, 1282726688, 1282851259, 1282964467, 1283065755, 1283154623, 1283230634, + 1283293412, 1283342644, 1283378085, 1283399556, 1283406948, 1283400219, 1283379398, 1283344582, 1283295937, + 1283233697, 1283158163, 1283069704, 1282968748, 1282855789, 1282731378, 1282596123, 1282450686, 1282295780, + 1282132162, 1281960636, 1281782040, 1281597253, 1281407178, 1281212748, 1281014916, 1280814653, 1280612938, + -1280410760, -1280209108, -1280008970, -1279811325, -1279617137, -1279427356, -1279242908, -1279064691, -1278893575, + -1278730391, -1278575934, -1278430953, -1278296152, -1278172183, -1278059646, -1277959085, -1277870984, -1277795766, + -1277733793, -1277685360, -1277650698, -1277629970, -1277623272, -1277630630, -1277652006, -1277687290, -1277736307, + -1277798815, -1277874509, -1277963018, -1278063911, -1278176696, -1278300826, -1278435697, -1278580655, -1278734998, + -1278897977, -1279068803, -1279246650, -1279430656, -1279619930, -1279813555, -1280010596, -1280210097, -1280411091, + -1280612606, -1280813664, -1281013290, -1281210515, -1281404382, -1281593947, -1281778291, -1281956514, -1282127749, + -1282291161, -1282445951, -1282591364, -1282726688, -1282851259, -1282964467, -1283065755, -1283154623, -1283230634, + -1283293412, -1283342644, -1283378085, -1283399556, -1283406948, -1283400219, -1283379398, -1283344582, -1283295937, + -1283233697, -1283158163, -1283069704, -1282968748, -1282855789, -1282731378, -1282596123, -1282450686, -1282295780, + -1282132162, -1281960636, -1281782040, -1281597240, -1281407124, -1281212613, -1281014638, -1280814136, -1280612044, + -1280409293, -1280206794, -1280005436, -1279806071, -1279609505, -1279416489, -1279227704, -1279043754, -1278865148, + -1278692290, -1278525466, -1278364827, -1278210380, -1278061967, -1277919259, -1277781732, -1277648661, -1277519103, + -1277391882, -1277265579, -1277138516, -1277008749, -1276874050, -1276731906, -1276579498, -1276413701, -1276231074, + -1276027848, -1275799922, -1275542858, -1275251868, -1274921816, -1274547202, -1274122161, -1273640454, -1273095459, + -1272480163, -1271787153, -1271008605, -1270136275, -1269161491, -1268075138, -1266867650, -1265529002, -1264048705, + -1262415795, -1260618834, -1258645914, -1256484654, -1254122219, -1251545330, -1248740288, -1245693001, -1242389021, + -1238813588, -1234951678, -1230788064, -1226307382, -1221494200, -1216333106, -1210808785, -1204906119, -1198610276, + -1191906816, -1184781789, -1177221841, -1169214319, -1160747375, -1151810067, -1142392460, -1132485722, -1122082216, + -1111175584, -1099760832, -1087834398, -1075394224, -1062439811, -1048972272, -1034994376, -1020510578, -1005527053, + -990051705, -974094182, -957665874, -940779904, -923451116, -905696046, -887532891, -868981469, -850063169, + -830800896, -811219007, -791343239, -771200631, -750819438, -730229039, -709459838, -688543157, -667511126, + -646396563, -625232849, -604053802, -582893543, -561786350, -540766526, -519868245, -499125406, -478571481, + -458239366, -438161227, -418368350, -398890991, -379758233, -360997846, -342636148, -324697881, -307206093, + -290182024, -273645013, -257612410, -242099504, -227119464, -212683299, -198799827, -185475666, -172715241, + -160520802, -148892465, -137828265, -127324223, -117374432, -107971150, -99104909, -90764635, -82937772, + -75610419, -68767471, -62392760, -56469205, -50978959, -45903556, -41224052, -36921169, -32975429, + -29367284, -26077235, -23085950, -20374365, -17923784, -15715959, -13733175, -11958308, -10374886, + -8967135, -7720017, -6619257, -5651362, -4803637, -4064184, -3421902, -2866477, -2388368, + -1978789, -1629681, -1333688, -1084125, -874947, -700710, -556540, -438092, -341515, + -263414, -200812, -151118, -112086, -81786, -58572, -41046, -28035, -18564, + -11827, -7166, -4052, -2065, -873, -219, 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, 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, 0, 0, 0, 0}; + +const Word32 LowDelayShapes_n960_N960_HRA_7_5ms_IP[1440] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 44, 108, 200, + 327, 496, 716, 997, 1352, 1793, 2334, 2993, 3788, + 4740, 5873, 7210, 8782, 10618, 12754, 15228, 18079, 21354, + 25102, 29375, 34232, 39736, 45954, 52960, 60833, 69657, 79523, + 90531, 102783, 116393, 131479, 148170, 166600, 186913, 209263, 233812, + 260731, 290202, 322417, 357578, 395898, 437601, 482924, 532113, 585429, + 643144, 705541, 772919, 845587, 923872, 1008108, 1098650, 1195861, 1300121, + 1411824, 1531379, 1659208, 1795748, 1941453, 2096787, 2262233, 2438287, 2625458, + 2824273, 3035270, 3259002, 3496037, 3746956, 4012353, 4292837, 4589026, 4901555, + 5231067, 5578220, 5943680, 6328125, 6732242, 7156730, 7602292, 8069643, 8559503, + 9072598, 9609661, 10171429, 10758643, 11372046, 12012385, 12680404, 13376850, 14102468, + 14858000, 15644185, 16461757, 17311444, 18193967, 19110038, 20060361, 21045626, 22066514, + 23123691, 24217808, 25349499, 26519382, 27728053, 28976092, 30264055, 31592472, 32961855, + 34372684, 35825415, 37320475, 38858262, 40439142, 42063449, 43731482, 45443509, 47199758, + 49000423, 50845659, 52735581, 54670266, 56649748, 58674020, 60743031, 62856690, 65014857, + 67217351, 69463943, 71754359, 74088280, 76465337, 78885116, 81347157, 83850949, 86395935, + 88981513, 91607029, 94271785, 96975035, 99715986, 102493800, 105307656, 108156591, 111039641, + 113955799, 116904014, 119883198, 122892222, 125929920, 128995090, 132086493, 135202860, 138342888, + 141505243, 144688567, 147891470, 151112543, 154350350, 157603439, 160870336, 164149553, 167439589, + 170738931, 174046055, 177359434, 180677535, 183998823, 187321766, 190644834, 193966503, 197285258, + 200599596, 203908028, 207209080, 210501300, 213783255, 217053539, 220310770, 223553598, 226780705, + 229990806, 233182654, 236355043, 239506805, 242636819, 245744010, 248827351, 251885864, 254918626, + 257924767, 260903473, 263853991, 266775622, 269667734, 272529755, 275361176, 278161556, 280930518, + 283667753, 286373022, 289046153, 291687043, 294295661, 296872047, 299416309, 301928628, 304409254, + 306858511, 309276789, 311664551, 314022327, 316350717, 318650389, 320922075, 323166575, 325384751, + 327577531, 329745900, 331890905, 334013649, 336115291, 338197045, 340260173, 342305990, 344335852, + 346351165, 348353370, 350343952, 352324427, 354296346, 356261288, 358220860, 360176691, 362130431, + 364083745, 366038312, 367995821, 369957968, 371926451, 373902968, 375889214, 377886876, 379897629, + 381923135, 383965040, 386024966, 388104513, 390205254, 392328729, 394476448, 396649881, 398850460, + 401079575, 403338572, 405628746, 407951345, 410307564, 412698544, 415125367, 417589059, 420090585, + 422630847, 425210685, 427830873, 430492120, 433195067, 435940288, 438728287, 441559502, 444434298, + 447352971, 450315749, 453322788, 456374176, 459469929, 462609996, 465794259, 469022529, 472294553, + 475610011, 478968518, 482369626, 485812825, 489297542, 492823148, 496388953, 499994212, 503638125, + 507319839, 511038449, 514793004, 518582502, 522405897, 526262100, 530149980, 534068367, 538016053, + 541991796, 545994319, 550022317, 554074452, 558149362, 562245659, 566361935, 570496756, 574648675, + 578816224, 582997925, 587192283, 591397795, 595612950, 599836228, 604066106, 608301058, 612539556, + 616780072, 621021084, 625261070, 629498515, 633731914, 637959769, 642180591, 646392905, 650595252, + 654786183, 658964269, 663128098, 667276277, 671407434, 675520217, 679613298, 683685373, 687735163, + 691761414, 695762900, 699738424, 703686816, 707606936, 711497676, 715357958, 719186737, 722983000, + 726745768, 730474096, 734167073, 737823824, 741443507, 745025319, 748568492, 752072293, 755536028, + 758959039, 762340704, 765680440, 768977700, 772231975, 775442794, 778609720, 781732356, 784810341, + 787843351, 790831096, 793773326, 796669823, 799520406, 802324927, 805083276, 807795372, 810461171, + 813080658, 815653853, 818180806, 820661596, 823096332, 825485155, 827828229, 830125749, 832377934, + 834585028, 836747302, 838865047, 840938578, 842968232, 844954366, 846897354, 848797592, 850655491, + 852471478, 854245997, 855979505, 857672472, 859325380, 860938723, 862513004, 864048738, 865546444, + 867006653, 868429898, 869816720, 871167666, 872483283, 873764126, 875010749, 876223709, 877403563, + 878550870, 879666189, 880750077, 881803089, 882825781, 883818705, 884782410, 885717445, 886624352, + 887503671, 888355939, 889181688, 889981445, 890755734, 891505074, 892229977, 892930955, 893608509, + 894263138, 894895337, 895505593, 896094389, 896662203, 897209507, 897736768, 898244447, 898733000, + 899202877, 899654523, 900088379, 900504877, 900904447, 901287510, 901654485, 902005783, 902341811, + 902662967, 902969647, 903262240, 903541129, 903806691, 904059297, 904299312, 904527095, 904742999, + 904947372, 905140554, 905322879, 905494676, 905656265, 905807964, 905950080, 906082916, 906206768, + 906321926, 906428673, 906527284, 906618032, 906701178, 906776980, 906845690, 906907551, 906962802, + 907011675, 907054396, 907091185, 907122257, 907147818, 907168073, 907183217, 907193443, 907198938, + 907199882, 907196451, 907188818, 907177150, 907161608, 907142351, 907119533, 907093305, 907063813, + 907031199, 906995603, 906957162, 906916008, 906872273, 906826083, 906777563, 906726837, 906674025, + 906619245, 906562613, 906504244, 906444251, 906382745, 906319835, 906255629, 906190236, 906123759, + 906056304, 905987975, 905918873, 905849099, 905778755, 905707939, 905636751, 905565287, 905493644, + 905421918, 905350204, 905278596, 905207187, 905136068, 905065331, 904995065, 904925359, 904856301, + 904787977, 904720472, 904653870, 904588254, 904523701, 904460295, 904398114, 904337234, 904277728, + 904219670, 904163129, 904108175, 904054874, 904003290, 903953487, 903905525, 903859462, 903815353, + 903773252, 903733209, 903695274, 903659492, 903625906, 903594557, 903565482, 903538716, 903514291, + 903492237, 903472579, 903455342, 903440546, 903428208, 903418343, 903410963, 903406076, 903403687, + 903403799, 903406411, 903411521, 903419121, 903429201, 903441750, 903456751, 903474186, 903494033, + 903516269, 903540866, 903567793, 903597018, 903628506, 903662217, 903698112, 903736145, 903776272, + 903818442, 903862605, 903908708, 903956694, 904006505, 904058081, 904111359, 904166274, 904222761, + 904280750, 904340172, 904400953, 904463022, 904526303, 904590718, 904656191, 904722641, 904789988, + 904858152, 904927048, 904996594, 905066706, 905137298, 905208286, 905279583, 905351102, 905422757, + 905494462, 905566128, 905637670, 905709001, 905780033, 905850681, 905920859, 905990482, 906059464, + 906127723, 906195175, 906261739, 906327332, 906391876, 906455291, 906517501, 906578429, 906638002, + 906696146, 906752790, 906807866, 906861306, 906913045, 906963019, 907011167, 907057430, 907101752, + 907144078, 907184355, 907222535, 907258571, 907292418, 907324034, 907353381, 907380422, 907405124, + 907427456, 907447391, 907464903, 907479970, 907492575, 907502701, 907510335, 907515468, 907518092, + 907518205, 907515805, 907510896, 907503482, 907493572, 907481179, 907466317, 907449004, 907429261, + 907407111, 907382581, 907355702, 907326506, 907295028, 907261307, 907225384, 907187302, 907147109, + 907104853, 907060585, 907014361, 906966236, 906916270, 906864523, 906811060, 906755944, 906699245, + 906641031, 906581374, 906520347, 906458025, 906394483, 906329801, 906264057, 906197332, 906129707, + 906061266, 905992093, 905922271, 905851888, 905781028, 905709780, 905638230, 905566465, 905494574, + -905422645, -905350765, -905279024, -905207507, -905136304, -905065500, -904995184, -904925439, -904856352, + -904788008, -904720488, -904653877, -904588254, -904523701, -904460295, -904398114, -904337234, -904277728, + -904219670, -904163129, -904108175, -904054874, -904003290, -903953487, -903905525, -903859462, -903815353, + -903773252, -903733209, -903695274, -903659492, -903625906, -903594557, -903565482, -903538716, -903514291, + -903492237, -903472579, -903455342, -903440546, -903428208, -903418343, -903410963, -903406076, -903403687, + -903403799, -903406411, -903411521, -903419121, -903429201, -903441750, -903456751, -903474186, -903494033, + -903516269, -903540866, -903567793, -903597018, -903628506, -903662217, -903698112, -903736145, -903776272, + -903818442, -903862605, -903908708, -903956694, -904006505, -904058081, -904111359, -904166274, -904222761, + -904280750, -904340172, -904400953, -904463022, -904526303, -904590718, -904656191, -904722641, -904789988, + -904858152, -904927048, -904996594, -905066706, -905137298, -905208286, -905279583, -905351102, -905422757, + -905494462, -905566128, -905637670, -905709001, -905780033, -905850681, -905920859, -905990482, -906059464, + -906127723, -906195175, -906261739, -906327332, -906391876, -906455291, -906517501, -906578429, -906638002, + -906696146, -906752790, -906807866, -906861306, -906913045, -906963019, -907011167, -907057430, -907101752, + -907144078, -907184355, -907222535, -907258571, -907292418, -907324034, -907353381, -907380422, -907405124, + -907427456, -907447391, -907464903, -907479970, -907492575, -907502701, -907510335, -907515468, -907518092, + -907518205, -907515805, -907510896, -907503482, -907493572, -907481179, -907466317, -907449004, -907429261, + -907407111, -907382581, -907355702, -907326506, -907295028, -907261307, -907225384, -907187302, -907147109, + -907104853, -907060585, -907014361, -906966236, -906916270, -906864523, -906811060, -906755944, -906699245, + -906641031, -906581374, -906520347, -906458025, -906394483, -906329801, -906264050, -906197315, -906129676, + -906061214, -905992012, -905922152, -905851718, -905780792, -905709459, -905637802, -905565904, -905493847, + -905421715, -905349587, -905277545, -905205668, -905134032, -905062714, -904991788, -904921326, -904851397, + -904782068, -904713403, -904645463, -904578305, -904511983, -904446548, -904382044, -904318513, -904255990, + -904194508, -904134091, -904074760, -904016528, -903959404, -903903387, -903848473, -903794647, -903741889, + -903690170, -903639452, -903589690, -903540829, -903492806, -903445546, -903398968, -903352977, -903307470, + -903262332, -903217440, -903172655, -903127830, -903082805, -903037408, -902991455, -902944749, -902897082, + -902848230, -902797958, -902746017, -902692145, -902636065, -902577487, -902516107, -902451605, -902383649, + -902311891, -902235969, -902155504, -902070104, -901979361, -901882852, -901780138, -901670764, -901554261, + -901430141, -901297903, -901157028, -901006979, -900847206, -900677140, -900496195, -900303767, -900099237, + -899881968, -899651302, -899406566, -899147069, -898872099, -898580929, -898272809, -897946972, -897602633, + -897238985, -896855201, -896450436, -896023825, -895574479, -895101492, -894603937, -894080864, -893531305, + -892954268, -892348742, -891713696, -891048075, -890350805, -889620793, -888856922, -888058059, -887223048, + -886350714, -885439866, -884489291, -883497761, -882464029, -881386834, -880264898, -879096929, -877881622, + -876617661, -875303716, -873938450, -872520516, -871048562, -869521229, -867937155, -866294976, -864593328, + -862830848, -861006177, -859117961, -857164854, -855145521, -853058635, -850902887, -848676980, -846379640, + -844009611, -841565658, -839046575, -836451182, -833778329, -831026896, -828195801, -825283996, -822290474, + -819214267, -816054453, -812810153, -809480538, -806064827, -802562292, -798972258, -795294106, -791527275, + -787671264, -783725629, -779689995, -775564045, -771347531, -767040273, -762642156, -758153138, -753573244, + -748902575, -744141301, -739289667, -734347993, -729316674, -724196178, -718987051, -713689917, -708305473, + -702834496, -697277838, -691636430, -685911277, -680103464, -674214150, -668244572, -662196041, -656069944, + -649867743, -643590972, -637241240, -630820227, -624329685, -617771433, -611147363, -604459432, -597709664, + -590900148, -584033037, -577110543, -570134942, -563108566, -556033804, -548913099, -541748950, -534543903, + -527300554, -520021545, -512709564, -505367338, -497997635, -490603260, -483187052, -475751882, -468300650, + -460836282, -453361728, -445879958, -438393963, -430906743, -423421316, -415940704, -408467938, -401006049, + -393558069, -386127025, -378715938, -371327818, -363965660, -356632445, -349331130, -342064650, -334835913, + -327647796, -320503142, -313404758, -306355410, -299357818, -292414658, -285528555, -278702079, -271937746, + -265238010, -258605264, -252041836, -245549983, -239131895, -232789684, -226525389, -220340970, -214238305, + -208219189, -202285333, -196438360, -190679806, -185011113, -179433635, -173948631, -168557267, -163260612, + -158059640, -152955229, -147948160, -143039115, -138228681, -133517347, -128905505, -124393450, -119981382, + -115669406, -111457534, -107345683, -103333681, -99421264, -95608082, -91893698, -88277589, -84759152, + -81337704, -78012482, -74782650, -71647299, -68605451, -65656059, -62798015, -60030148, -57351228, + -54759972, -52255046, -49835065, -47498599, -45244179, -43070293, -40975397, -38957912, -37016231, + -35148723, -33353731, -31629581, -29974582, -28387030, -26865208, -25407397, -24011868, -22676893, + -21400745, -20181701, -19018041, -17908057, -16850050, -15842335, -14883242, -13971116, -13104325, + -12281255, -11500315, -10759938, -10058585, -9394741, -8766919, -8173665, -7613552, -7085185, + -6587202, -6118273, -5677102, -5262427, -4873021, -4507690, -4165278, -3844660, -3544752, + -3264499, -3002887, -2758933, -2531691, -2320249, -2123731, -1941292, -1772123, -1615446, + -1470519, -1336627, -1213092, -1099261, -994515, -898263, -809943, -729021, -654988, + -587365, -525695, -469547, -418515, -372215, -330284, -292383, -258192, -227410, + -199757, -174969, -152801, -133024, -115424, -99803, -85978, -73777, -63042, + -53629, -45403, -38240, -32028, -26663, -22051, -18104, -14745, -11902, + -9511, -7514, -5860, -4500, -3394, -2503, -1797, -1244, -820, + -502, -271, -109, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif /* #ifdef CR8_G_ADD_75MS */ + +RAM_ALIGN const Word32 LowDelayShapes_n960_N480_HRA_2_5ms_IP[240] = { + 214, 1407, 4144, 9592, 19434, 36052, 62711, 103783, 164992, + 253687, 379148, 552904, 789076, 1104722, 1520198, 2059494, 2750561, 3625602, + 4721314, 6079061, 7744972, 9769942, 12209518, 15123669, 18576419, 22635352, 27370973, + 32855950, 39164229, 46370051, 54546874, 63766241, 74096597, 85602085, 98341344, 112366317, + 127721101, 144440829, 162550610, 182064542, 202984778, 225300694, 248988134, 274008783, 300309659, + 327822776, 356464985, 386138051, 416728983, 448110659, 480142780, 512673177, 545539472, 578571104, + 611591694, 644421704, 676881340, 708793602, 739987407, 770300656, 799583149, 827699226, 854530045, + 879975405, 903955057, 926409465, 947300009, 966608644, 984337071, 1000505451, 1015150768, 1028324899, + 1040092491, 1050528715, 1059716983, 1067746699, 1074711082, 1080705143, 1085823820, 1090160324, 1093804700, + 1096842623, 1099354431, 1101414399, 1103090233, 1104442796, 1105526028, 1106387052, 1107066439, 1107598605, + 1108012308, 1108331223, 1108574556, 1108757676, 1108892731, 1108989242, 1109054637, 1109094735, 1109114155, + 1109116652, 1109105394, 1109083163, 1109052498, 1109015788, 1108975323, 1108933307, 1108891843, 1108852902, + 1108818280, 1108789546, 1108767992, 1108754591, 1108749953, 1108754306, 1108767481, 1108788919, 1108817694, + 1108852552, 1108891964, 1108934195, -1108977380, -1109019614, -1109059032, -1109093898, -1109122681, -1109144125, + -1109157302, -1109161650, -1109156995, -1109143556, -1109121925, -1109093037, -1109058122, -1109018637, -1108976187, + -1108932433, -1108888980, -1108847255, -1108808366, -1108772946, -1108740971, -1108711558, -1108682731, -1108651158, + -1108611855, -1108557851, -1108479820, -1108365676, -1108200143, -1107964292, -1107635083, -1107184891, -1106581062, + -1105785503, -1104754330, -1103437601, -1101779148, -1099716548, -1097181229, -1094098763, -1090389339, -1085968441, + -1080747748, -1074636248, -1067541577, -1059371579, -1050036059, -1039448713, -1027529209, -1014205354, -999415302, + -983109740, -965253961, -945829756, -924837032, -902295070, -878243367, -852741971, -825871301, -797731403, + -768440669, -738134051, -706960817, -675081952, -642667284, -609892453, -576935833, -543975515, -511186440, + -478737764, -446790521, -415495622, -384992199, -355406317, -326850029, -299420751, -273200929, -248257970, + -224644391, -202398148, -181543141, -162089834, -144035993, -127367520, -112059369, -98076525, -85375063, + -73903244, -63602666, -54409446, -46255413, -39069306, -32777951, -27307388, -22583946, -18535216, + -15090941, -12183768, -9749883, -7729511, -6067277, -4712439, -3619003, -2745721, -2055997, + -1517713, -1102987, -787888, -552109, -378629, -253358, -164789, -103664, -62644, + -36017, -19417, -9584, -4141, -1406, -214 }; +RAM_ALIGN const Word32 LowDelayShapes_n960_N480_HRA_5ms_IP[420] = { + 153, 1006, 2962, 6854, 13880, 25735, 44738, 73986, 117524, + 180533, 269534, 392603, 559593, 782368, 1075031, 1454143, 1938937, 2551502, + 3316947, 4263524, 5422707, 6829222, 8521011, 10539137, 12927604, 15733109, 19004698, + 22793344, 27151431, 32132152, 37788816, 44174082, 51339114, 59332667, 68200136, 77982547, + 88715548, 100428385, 113142910, 126872625, 141621804, 157384706, 174144915, 191874817, 210535261, + 230075406, 250432778, 271533559, 293293106, 315616716, 338400617, 361533198, 384896437, 408367524, + 431820627, 455128780, 478165843, 500808481, 522938120, 544442827, 565219197, 585174124, 604225689, + 622304754, 639355717, 655337129, 670221993, 683997778, 696666136, 708242355, 718754575, 728242788, + 736757688, 744359378, 751116012, 757102394, 762398585, 767088551, 771258886, 774997644, 778393288, + 781533768, 784505744, 787393944, 790280637, 793245232, 796363956, 799709608, 803351363, 807354601, + 811780739, 816687064, 822126537, 828147569, 834793773, 842103681, 850110443, 858841520, 868318369, + 878556163, 889563529, 901342346, 913887605, 927187338, 941222645, 955967800, 971390453, 987451937, + 1004107649, 1021307531, 1038996616, 1057115651, 1075601769, 1094389201, 1113410024, 1132594917, 1151873921, + 1171177186, 1190435688, 1209581916, 1228550504, 1247278803, 1265707395, 1283780533, 1301446498, 1318657893, + 1335371854, 1351550191, 1367159457, 1382170967, 1396560748, 1410309460, 1423402271, 1435828702, 1447582463, + 1458661263, 1469066617, 1478803649, 1487880888, 1496310057, 1504105864, 1511285781, 1517869810, 1523880240, + 1529341392, 1534279342, 1538721639, 1542697001, 1546235012, 1549365809, 1552119778, 1554527246, 1556618203, + 1558422028, 1559967247, 1561281317, 1562390436, 1563319395, 1564091445, 1564728213, 1565249633, 1565673917, + 1566017543, 1566295272, 1566520181, 1566703721, 1566855785, 1566984788, 1567097770, 1567200488, 1567297538, + 1567392456, 1567487845, 1567585484, 1567686442, 1567791191, 1567899701, 1568011546, 1568125984, 1568242042, + 1568358534, 1568474289, 1568587995, 1568698311, 1568803945, 1568903672, 1568996349, 1569080932, 1569156484, + 1569222192, 1569277370, 1569321465, 1569354064, 1569374893, 1569383815, 1569380829, 1569366065, 1569339781, + 1569302349, 1569254257, 1569196093, 1569128539, 1569052361, 1568968403, 1568877571, 1568780830, 1568679193, + 1568573710, 1568465461, 1568355548, 1568245083, 1568135185, 1568026967, 1567921528, 1567819946, 1567723271, + 1567632511, 1567548628, 1567472527, 1567405047, 1567346952, 1567298919, 1567261537, 1567235287, 1567220544, + 1567217562, 1567226472, 1567247272, 1567279829, 1567323868, 1567378978, 1567444612, 1567520086, 1567604589, + 1567697189, 1567796846, 1567902419, 1568012687, 1568126359, 1568242097, -1568358534, -1568474289, -1568587995, + -1568698311, -1568803945, -1568903672, -1568996349, -1569080932, -1569156484, -1569222192, -1569277370, -1569321465, + -1569354064, -1569374893, -1569383815, -1569380829, -1569366065, -1569339781, -1569302349, -1569254257, -1569196093, + -1569128539, -1569052361, -1568968403, -1568877571, -1568780830, -1568679193, -1568573710, -1568465461, -1568355548, + -1568245083, -1568135185, -1568026967, -1567921528, -1567819946, -1567723271, -1567632511, -1567548628, -1567472527, + -1567405047, -1567346952, -1567298919, -1567261537, -1567235287, -1567220544, -1567217562, -1567226472, -1567247272, + -1567279829, -1567323868, -1567378978, -1567444612, -1567520086, -1567604589, -1567697189, -1567796846, -1567902419, + -1568012687, -1568126359, -1568242097, -1568358479, -1568473914, -1568586854, -1568695591, -1568798286, -1568892916, + -1568977226, -1569048656, -1569104263, -1569140635, -1569153790, -1569139071, -1569091028, -1569003308, -1568868529, + -1568678156, -1568422382, -1568089999, -1567668277, -1567142834, -1566497514, -1565714254, -1564772952, -1563651331, + -1562324794, -1560766278, -1558946098, -1556831792, -1554387964, -1551576132, -1548354584, -1544678268, -1540498696, + -1535763912, -1530418507, -1524403718, -1517657618, -1510115411, -1501709847, -1492371764, -1482030768, -1470616033, + -1458057247, -1444285654, -1429235205, -1412843785, -1395054486, -1375816907, -1355088440, -1332835519, -1309034797, + -1283674224, -1256753995, -1228287351, -1198301206, -1166836586, -1133948872, -1099707826, -1064197417, -1027515419, + -989772809, -951092956, -911610610, -871470715, -830827045, -789840682, -748678366, -707510713, -666510349, + -625849956, -585700281, -546228117, -507594292, -469951710, -433443460, -398201053, -364342807, -331972440, + -301177891, -272030413, -244583969, -218874947, -194922208, -172727465, -152275991, -133537623, -116468025, + -101010189, -87096098, -74648510, -63582812, -53808877, -45232880, -37759037, -31291209, -25734358, + -20995832, -16986455, -13621428, -10821035, -8511162, -6623645, -5096451, -3873717, -2905668, + -2148423, -1563717, -1118555, -784819, -538834, -360926, -234965, -147925, -89451, + -51458, -27754, -13704, -5923, -2011, -306 }; +RAM_ALIGN const Word32 LowDelayShapes_n960_N480_HRA_IP[780] = { + 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, 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, 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, 105, 687, 2025, 4688, 9502, 17634, + 30689, 50817, 80838, 124375, 186009, 271432, 387623, 543017, 747676, + 1013467, 1354215, 1785853, 2326545, 2996777, 3819424, 4819763, 6025441, 7466392, + 9174686, 11184326, 13530961, 16251545, 19383921, 22966334, 27036891, 31632957, 36790505, + 42543426, 48922816, 55956247, 63667042, 72073568, 81188571, 91018551, 101563225, 112815065, + 124758945, 137371906, 150623045, 164473553, 178876885, 193779093, 209119296, 224830297, 240839344, + 257069006, 273438164, 289863100, 306258645, 322539389, 338620907, 354420979, 369860792, 384866072, + 399368244, 413305531, 426623420, 439275707, 451224957, 462442920, 472910759, 482619111, 491567983, + 499766479, 507232383, 513991603, 520077504, 525530145, 530395443, 534724296, 538571682, 541995756, + 545056975, 547817267, 550339253, 552685542, 554918106, 557097730, 559283544, 561532631, 563899693, + 566436780, 569193061, 572214618, 575544274, 579221418, 583281849, 587757606, 592676805, 598063482, + 603937430, 610314061, 617204279, 624614388, 632546030, 640996174, 649957147, 659416723, 669358259, + 679760895, 690599795, 701846444, 713468981, 725432569, 737699796, 750231092, 762985159, 775919415, + 788990419, 802154306, 815367198, 828585593, 841766740, 854868978, 867852045, 880677358, 893308258, + 905710214, 917851001, 929700832, 941232469, 952421292, 963245346, 973685357, 983724726, 993349512, + 1002548385, 1011312579, 1019635831, 1027514316, 1034946573, 1041933433, 1048477942, 1054585275, 1060262649, + 1065519228, 1070366010, 1074815711, 1078882625, 1082582470, 1085932219, 1088949913, 1091654462, 1094065430, + 1096202822, 1098086863, 1099737781, 1101175600, 1102419947, 1103489872, 1104403690, 1105178850, 1105831817, + 1106377989, 1106831632, 1107205842, 1107512525, 1107762397, 1107965009, 1108128778, 1108261042, 1108368118, + 1108455375, 1108527311, 1108587638, 1108639366, 1108684891, 1108726077, 1108764338, 1108800715, 1108835945, + 1108870522, 1108904754, 1108938811, 1108972723, 1109006542, 1109040205, 1109073607, 1109106645, 1109139216, + 1109171221, 1109202563, 1109233147, 1109262880, 1109291675, 1109319447, 1109346114, 1109371602, 1109395837, + 1109418753, 1109440288, 1109460385, 1109478991, 1109496061, 1109511552, 1109525430, 1109537663, 1109548227, + 1109557101, 1109564272, 1109569731, 1109573473, 1109575498, 1109575814, 1109574431, 1109571363, 1109566630, + 1109560257, 1109552270, 1109542702, 1109531587, 1109518966, 1109504879, 1109489374, 1109472496, 1109454299, + 1109434835, 1109414161, 1109392335, 1109369417, 1109345469, 1109320555, 1109294742, 1109268095, 1109240684, + 1109212578, 1109183848, 1109154564, 1109124800, 1109094627, 1109064121, 1109033354, 1109002402, 1108971338, + 1108940237, 1108909175, 1108878226, 1108847464, 1108816965, 1108786801, 1108757046, 1108727774, 1108699056, + 1108670963, 1108643567, 1108616936, 1108591139, 1108566243, 1108542312, 1108519412, 1108497603, 1108476946, + 1108457499, 1108439319, 1108422458, 1108406967, 1108392895, 1108380286, 1108369184, 1108359626, 1108351647, + 1108345281, 1108340553, 1108337489, 1108336107, 1108336422, 1108338446, 1108342183, 1108347636, 1108354799, + 1108363664, 1108374217, 1108386437, 1108400301, 1108415777, 1108432830, 1108451419, 1108471498, 1108493014, + 1108515912, 1108540129, 1108565598, 1108592247, 1108620001, 1108648779, 1108678497, 1108709066, 1108740395, + 1108772389, 1108804951, 1108837980, 1108871376, 1108905035, 1108938852, 1108972723, 1109006542, 1109040205, + 1109073607, 1109106645, 1109139216, 1109171221, 1109202563, 1109233147, 1109262880, 1109291675, 1109319447, + 1109346114, 1109371602, 1109395837, 1109418753, 1109440288, 1109460385, 1109478991, 1109496061, 1109511552, + 1109525430, 1109537663, 1109548227, 1109557101, 1109564272, 1109569731, 1109573473, 1109575498, 1109575814, + 1109574431, 1109571363, 1109566630, 1109560257, 1109552270, 1109542702, 1109531587, 1109518966, 1109504879, + 1109489374, 1109472496, 1109454299, 1109434835, 1109414161, 1109392335, 1109369417, 1109345469, 1109320555, + 1109294742, 1109268095, 1109240684, 1109212578, 1109183848, 1109154564, 1109124800, 1109094627, 1109064121, + 1109033354, 1109002402, 1108971338, -1108940237, -1108909175, -1108878226, -1108847464, -1108816965, -1108786801, + -1108757046, -1108727774, -1108699056, -1108670963, -1108643567, -1108616936, -1108591139, -1108566243, -1108542312, + -1108519412, -1108497603, -1108476946, -1108457499, -1108439319, -1108422458, -1108406967, -1108392895, -1108380286, + -1108369184, -1108359626, -1108351647, -1108345281, -1108340553, -1108337489, -1108336107, -1108336422, -1108338446, + -1108342183, -1108347636, -1108354799, -1108363664, -1108374217, -1108386437, -1108400301, -1108415777, -1108432830, + -1108451419, -1108471498, -1108493014, -1108515912, -1108540129, -1108565598, -1108592247, -1108620001, -1108648779, + -1108678497, -1108709066, -1108740395, -1108772389, -1108804951, -1108837980, -1108871376, -1108905035, -1108938852, + -1108972723, -1109006542, -1109040205, -1109073607, -1109106645, -1109139216, -1109171221, -1109202563, -1109233147, + -1109262880, -1109291675, -1109319447, -1109346114, -1109371602, -1109395837, -1109418753, -1109440288, -1109460385, + -1109478991, -1109496061, -1109511552, -1109525430, -1109537663, -1109548227, -1109557101, -1109564272, -1109569731, + -1109573473, -1109575498, -1109575814, -1109574431, -1109571363, -1109566630, -1109560257, -1109552270, -1109542702, + -1109531587, -1109518966, -1109504879, -1109489374, -1109472496, -1109454299, -1109434835, -1109414161, -1109392335, + -1109369417, -1109345469, -1109320555, -1109294742, -1109268095, -1109240684, -1109212578, -1109183848, -1109154564, + -1109124800, -1109094627, -1109064121, -1109033354, -1109002402, -1108971338, -1108940237, -1108909175, -1108878226, + -1108847464, -1108816965, -1108786801, -1108757046, -1108727774, -1108699056, -1108670963, -1108643567, -1108616936, + -1108591139, -1108566243, -1108542312, -1108519412, -1108497603, -1108476946, -1108457499, -1108439319, -1108422458, + -1108406967, -1108392895, -1108380286, -1108369184, -1108359626, -1108351647, -1108345281, -1108340553, -1108337489, + -1108336107, -1108336422, -1108338446, -1108342183, -1108347636, -1108354799, -1108363664, -1108374217, -1108386437, + -1108400301, -1108415777, -1108432830, -1108451419, -1108471498, -1108493014, -1108515912, -1108540129, -1108565598, + -1108592247, -1108620001, -1108648779, -1108678497, -1108709066, -1108740395, -1108772389, -1108804951, -1108837980, + -1108871376, -1108905035, -1108938852, -1108972682, -1109006261, -1109039351, -1109071571, -1109102407, -1109131162, + -1109156896, -1109178374, -1109193989, -1109201688, -1109198891, -1109182406, -1109148336, -1109091993, -1109007805, + -1108889225, -1108728643, -1108517302, -1108245211, -1107901063, -1107472158, -1106944320, -1106301824, -1105527310, + -1104601707, -1103504157, -1102211925, -1100700333, -1098942681, -1096910184, -1094571927, -1091894839, -1088843693, + -1085381150, -1081467851, -1077062556, -1072122362, -1066602975, -1060459071, -1053644721, -1046113898, -1037821043, + -1028721699, -1018773190, -1007935330, -996171157, -983447669, -969736537, -955014802, -939265519, -922478340, + -904650040, -885784954, -865895333, -845001612, -823132583, -800325469, -776625909, -752087844, -726773304, + -700752110, -674101477, -646905528, -619254721, -591245188, -562977986, -534558266, -506094363, -477696807, + -449477265, -421547413, -394017760, -366996430, -340587909, -314891801, -290001587, -266003441, -242975106, + -220984887, -200090776, -180339738, -161767200, -144396752, -128240072, -113297104, -99556455, -86996029, + -75583860, -65279122, -56033278, -47791333, -40493145, -34074759, -28469709, -23610284, -19428682, + -15858075, -12833534, -10292814, -8176993, -6430970, -5003818, -3849000, -2924474, -2192679, + -1620441, -1178790, -842729, -590941, -405483, -271445, -176613, -111130, -67168, + -38622, -20823, -10279, -4442, -1508, -229 }; +RAM_ALIGN const Word32 LowDelayShapes_n960_N960_HRA_2_5ms_IP[480] = { + 214, 718, 1564, 2887, 4850, 7655, 11549, 16828, 23847, + 33024, 44855, 59914, 78870, 102494, 131671, 167412, 210862, 263320, + 326247, 401279, 490246, 595184, 718349, 862234, 1029583, 1223409, 1447008, + 1703973, 1998212, 2333963, 2715805, 3148674, 3637878, 4189104, 4808432, 5502344, + 6277732, 7141903, 8102584, 9167924, 10346495, 11647288, 13079711, 14653577, 16379097, + 18266869, 20327854, 22573365, 25015043, 27664828, 30534935, 33637823, 36986159, 40592781, + 44470665, 48632874, 53092523, 57862728, 62956563, 68387004, 74166887, 80308851, 86825288, + 93728290, 101029595, 108740533, 116871978, 125434289, 134437259, 143890065, 153801219, 164178510, + 175028964, 186358792, 198173341, 210477054, 223273422, 236564945, 250353087, 264638241, 279419691, + 294695574, 310462852, 326717278, 343453367, 360664374, 378342268, 396477718, 415060072, 434077349, + 453516232, 473362064, 493598851, 514209273, 535174695, 556475190, 578089564, 599995393, 622169062, + 644585817, 667219821, 690044217, 713031208, 736152130, 759377547, 782677345, 806020840, 829376886, + 852713991, 876000447, 899204452, 922294246, 945238242, 968005170, 990564209, 1012885127, 1034938418, + 1056695435, 1078128516, 1099211112, 1119917901, 1140224902, 1160109567, 1179550884, 1198529445, 1217027528, + 1235029144, 1252520091, 1269487982, 1285922269, 1301814250, 1317157066, 1331945687, 1346176884, 1359849191, + 1372962859, 1385519797, 1397523511, 1408979025, 1419892807, 1430272680, 1440127732, 1449468226, 1458305498, + 1466651859, 1474520500, 1481925383, 1488881148, 1495403011, 1501506666, 1507208191, 1512523957, 1517470536, + 1522064619, 1526322933, 1530262165, 1533898889, 1537249499, 1540330149, 1543156689, 1545744622, 1548109049, + 1550264632, 1552225553, 1554005489, 1555617576, 1557074399, 1558387963, 1559569689, 1560630404, 1561580336, + 1562429115, 1563185777, 1563858772, 1564455973, 1564984695, 1565451702, 1565863235, 1566225027, 1566542325, + 1566819919, 1567062160, 1567272989, 1567455965, 1567614286, 1567750818, 1567868122, 1567968477, 1568053906, + 1568126199, 1568186936, 1568237509, 1568279142, 1568312908, 1568339752, 1568360503, 1568375889, 1568386553, + 1568393062, 1568395921, 1568395582, 1568392450, 1568386895, 1568379252, 1568369831, 1568358921, 1568346793, + 1568333699, 1568319881, 1568305568, 1568290979, 1568276322, 1568261795, 1568247587, 1568233876, 1568220830, + 1568208605, 1568197346, 1568187184, 1568178237, 1568170607, 1568164384, 1568159638, 1568156425, 1568154783, + 1568154732, 1568156276, 1568159400, 1568164071, 1568170240, 1568177841, 1568186791, 1568196993, 1568208336, + 1568220695, 1568233934, 1568247907, 1568262461, 1568277433, 1568292659, -1568307970, -1568323196, -1568338169, + -1568352723, -1568366698, -1568379938, -1568392298, -1568403642, -1568413846, -1568422797, -1568430399, -1568436568, + -1568441238, -1568444360, -1568445899, -1568445842, -1568444189, -1568440959, -1568436189, -1568429930, -1568422249, + -1568413227, -1568402961, -1568391555, -1568379128, -1568365802, -1568351710, -1568336985, -1568321763, -1568306179, + -1568290362, -1568274432, -1568258500, -1568242658, -1568226981, -1568211514, -1568196277, -1568181247, -1568166364, + -1568151514, -1568136526, -1568121163, -1568105112, -1568087973, -1568069251, -1568048342, -1568024520, -1567996924, + -1567964542, -1567926198, -1567880531, -1567825982, -1567760771, -1567682880, -1567590033, -1567479671, -1567348935, + -1567194644, -1567013268, -1566800908, -1566553276, -1566265667, -1565932945, -1565549513, -1565109302, -1564605744, + -1564031762, -1563379748, -1562641555, -1561808482, -1560871269, -1559820088, -1558644542, -1557333666, -1555875931, + -1554259255, -1552471010, -1550498044, -1548326699, -1545942840, -1543331880, -1540478822, -1537368293, -1533984594, + -1530311749, -1526333557, -1522033659, -1517395595, -1512402882, -1507039082, -1501287884, -1495133187, -1488559185, + -1481550459, -1474092069, -1466169648, -1457769502, -1448878707, -1439485206, -1429577913, -1419146803, -1408183016, + -1396678943, -1384628319, -1372026306, -1358869573, -1345156368, -1330886582, -1316061806, -1300685380, -1284762427, + -1268299884, -1251306514, -1233792909, -1215771486, -1197256464, -1178263828, -1158811290, -1138918228, -1118605615, + -1097895946, -1076813140, -1055382446, -1033630329, -1011584359, -989273085, -966725907, -943972946, -921044904, + -897972934, -874788497, -851523227, -828208798, -804876792, -781558570, -758285150, -735087092, -711994385, + -689036342, -666241506, -643637563, -621251256, -599108313, -577233388, -555649994, -534380464, -513445903, + -492866154, -472659775, -452844015, -433434798, -414446719, -395893041, -377785693, -360135279, -342951091, + -326241124, -310012090, -294269448, -279017421, -264259031, -249996126, -236229411, -222958488, -210181887, + -197897110, -186100669, -174788126, -163954142, -153592518, -143696242, -134257536, -125267909, -116718201, + -108598638, -100898882, -93608083, -86714933, -80207718, -74074369, -68302521, -62879558, -57792672, + -53028908, -48575221, -44418518, -40545711, -36943757, -33599707, -30500746, -27634227, -24987716, + -22549018, -20306212, -18247679, -16362124, -14638601, -13066533, -11635723, -10336374, -9159092, + -8094899, -7135237, -6271969, -5497377, -4804166, -4185453, -3634765, -3146030, -2713568, + -2332079, -1996632, -1702653, -1445912, -1222503, -1028839, -861625, -717855, -594786, + -489927, -401025, -326046, -263164, -210741, -167319, -131601, -102441, -78831, + -59886, -44835, -33011, -23837, -16822, -11545, -7652, -4848, -2886, + -1564, -718, -214 }; +RAM_ALIGN const Word32 LowDelayShapes_n960_N960_HRA_5ms_IP[840] = { + 76, 257, 559, 1032, 1734, 2736, 4127, 6013, 8519, + 11795, 16017, 21388, 28146, 36565, 46958, 59681, 75141, 93793, + 116154, 142798, 174368, 211576, 255213, 306147, 365337, 433830, 512771, + 603404, 707083, 825270, 959545, 1111607, 1283278, 1476512, 1693391, 1936135, + 2207099, 2508779, 2843816, 3214988, 3625222, 4077586, 4575292, 5121693, 5720282, + 6374686, 7088668, 7866117, 8711044, 9627575, 10619947, 11692493, 12849640, 14095892, + 15435823, 16874063, 18415286, 20064193, 21825499, 23703917, 25704138, 27830817, 30088554, + 32481870, 35015193, 37692833, 40518962, 43497594, 46632560, 49927486, 53385775, 57010578, + 60804774, 64770951, 68911378, 73227988, 77722354, 82395670, 87248734, 92281923, 97495181, + 102888003, 108459414, 114207966, 120131717, 126228227, 132494547, 138927218, 145522261, 152275182, + 159180971, 166234104, 173428552, 180757788, 188214801, 195792105, 203481764, 211275403, 219164235, + 227139085, 235190416, 243308359, 251482745, 259703138, 267958873, 276239090, 284532776, 292828806, + 301115982, 309383080, 317618887, 325812253, 333952128, 342027608, 350027981, 357942764, 365761752, + 373475051, 381073123, 388546818, 395887478, 403086861, 410137202, 417031278, 423762414, 430324505, + 436712040, 442920115, 448944445, 454781381, 460427907, 465881653, 471140887, 476204517, 481072084, + 485743749, 490220286, 494503064, 498594029, 502495687, 506211078, 509743756, 513097759, 516277584, + 519288161, 522134817, 524823252, 527359505, 529749922, 532001128, 534119994, 536113606, 537989238, + 539754317, 541416403, 542983151, 544462298, 545861626, 547188947, 548452077, 549658817, 550816937, + 551934153, 553018114, 554076391, 555116460, 556145691, 557171340, 558200539, 559240287, 560297445, + 561378728, 562490702, 563639778, 564832206, 566074075, 567371305, 568729649, 570154682, 571651805, + 573226236, 574883010, 576626970, 578462769, 580394858, 582427488, 584564698, 586810313, 589167940, + 591640954, 594232500, 596945481, 599782552, 602746115, 605838312, 609061015, 612415825, 615904060, + 619526756, 623284658, 627178213, 631207574, 635372590, 639672804, 644107457, 648675483, 653375510, + 658205862, 663164563, 668249336, 673457615, 678786542, 684232980, 689793518, 695464480, 701241935, + 707121707, 713099387, 719170342, 725329733, 731572527, 737893509, 744287298, 750748363, 757271038, + 763849540, 770477982, 777150393, 783860731, 790602903, 797370781, 804158216, 810959059, 817767172, + 824576448, 831380824, 838174297, 844950938, 851704905, 858430460, 865121975, 871773953, 878381029, + 884937988, 891439772, 897881487, 904258415, 910566018, 916799945, 922956036, 929030332, 935019072, + 940918701, 946725867, 952437431, 958050459, 963562228, 968970222, 974272134, 979465863, 984549513, + 989521388, 994379992, 999124027, 1003752385, 1008264148, 1012658583, 1016935141, 1021093445, 1025133296, + 1029054661, 1032857672, 1036542620, 1040109952, 1043560268, 1046894310, 1050112965, 1053217256, 1056208338, + 1059087494, 1061856131, 1064515771, 1067068050, 1069514712, 1071857603, 1074098665, 1076239931, 1078283519, + 1080231627, 1082086525, 1083850551, 1085526101, 1087115629, 1088621631, 1090046648, 1091393252, 1092664044, + 1093861644, 1094988685, 1096047808, 1097041655, 1097972860, 1098844046, 1099657818, 1100416756, 1101123410, + 1101780297, 1102389891, 1102954625, 1103476879, 1103958984, 1104403212, 1104811774, 1105186822, 1105530438, + 1105844638, 1106131370, 1106392508, 1106629854, 1106845137, 1107040012, 1107216060, 1107374784, 1107517617, + 1107645915, 1107760961, 1107863967, 1107956073, 1108038347, 1108111792, 1108177340, 1108235860, 1108288159, + 1108334979, 1108377006, 1108414868, 1108449137, 1108480336, 1108508935, 1108535359, 1108559986, 1108583153, + 1108605158, 1108626260, 1108646685, 1108666625, 1108686243, 1108705675, 1108725031, 1108744398, 1108763843, + 1108783413, 1108803139, 1108823037, 1108843110, 1108863348, 1108883733, 1108904238, 1108924827, 1108945461, + 1108966087, 1108986655, 1109007132, 1109027458, 1109047572, 1109067415, 1109086928, 1109106055, 1109124739, + 1109142927, 1109160566, 1109177606, 1109193997, 1109209694, 1109224653, 1109238833, 1109252194, 1109264701, + 1109276321, 1109287024, 1109296781, 1109305569, 1109313366, 1109320154, 1109325918, 1109330645, 1109334328, + 1109336959, 1109338535, 1109339057, 1109338528, 1109336954, 1109334342, 1109330704, 1109326055, 1109320411, + 1109313791, 1109306216, 1109297711, 1109288301, 1109278014, 1109266881, 1109254934, 1109242206, 1109228734, + 1109214554, 1109199706, 1109184228, 1109168164, 1109151555, 1109134445, 1109116879, 1109098903, 1109080563, + 1109061906, 1109042980, 1109023833, 1109004515, 1108985073, 1108965557, 1108946017, 1108926503, 1108907062, + 1108887746, 1108868601, 1108849679, 1108831026, 1108812690, 1108794719, 1108777158, 1108760054, 1108743451, + 1108727393, 1108711923, 1108697081, 1108682908, 1108669442, 1108656721, 1108644781, 1108633654, 1108623374, + 1108613969, 1108605469, 1108597899, 1108591283, 1108585643, 1108580997, 1108577362, 1108574752, 1108573178, + 1108572650, 1108573172, 1108574747, 1108577376, 1108581056, 1108585780, 1108591541, 1108598324, 1108606116, + 1108614899, 1108624650, 1108635346, 1108646959, 1108659460, 1108672814, 1108686987, 1108701939, 1108717629, + 1108734013, 1108751046, 1108768679, 1108786861, 1108805540, 1108824662, 1108844171, 1108864011, 1108884121, + 1108904445, 1108924921, 1108945488, -1108966087, -1108986655, -1109007132, -1109027458, -1109047572, -1109067415, + -1109086928, -1109106055, -1109124739, -1109142927, -1109160566, -1109177606, -1109193997, -1109209694, -1109224653, + -1109238833, -1109252194, -1109264701, -1109276321, -1109287024, -1109296781, -1109305569, -1109313366, -1109320154, + -1109325918, -1109330645, -1109334328, -1109336959, -1109338535, -1109339057, -1109338528, -1109336954, -1109334342, + -1109330704, -1109326055, -1109320411, -1109313791, -1109306216, -1109297711, -1109288301, -1109278014, -1109266881, + -1109254934, -1109242206, -1109228734, -1109214554, -1109199706, -1109184228, -1109168164, -1109151555, -1109134445, + -1109116879, -1109098903, -1109080563, -1109061906, -1109042980, -1109023833, -1109004515, -1108985073, -1108965557, + -1108946017, -1108926503, -1108907062, -1108887746, -1108868601, -1108849679, -1108831026, -1108812690, -1108794719, + -1108777158, -1108760054, -1108743451, -1108727393, -1108711923, -1108697081, -1108682908, -1108669442, -1108656721, + -1108644781, -1108633654, -1108623374, -1108613969, -1108605469, -1108597899, -1108591283, -1108585643, -1108580997, + -1108577362, -1108574752, -1108573178, -1108572650, -1108573172, -1108574747, -1108577376, -1108581056, -1108585780, + -1108591541, -1108598324, -1108606116, -1108614899, -1108624650, -1108635346, -1108646959, -1108659460, -1108672814, + -1108686987, -1108701939, -1108717629, -1108734013, -1108751046, -1108768679, -1108786861, -1108805540, -1108824662, + -1108844171, -1108864011, -1108884121, -1108904445, -1108924921, -1108945488, -1108966059, -1108986562, -1109006925, + -1109027070, -1109046909, -1109066353, -1109085302, -1109103653, -1109121290, -1109138090, -1109153916, -1109168619, + -1109182038, -1109193990, -1109204280, -1109212687, -1109218972, -1109222869, -1109224086, -1109222302, -1109217164, + -1109208286, -1109195243, -1109177572, -1109154771, -1109126288, -1109091528, -1109049845, -1109000541, -1108942861, + -1108875994, -1108799068, -1108711146, -1108611228, -1108498242, -1108371047, -1108228427, -1108069090, -1107891663, + -1107694692, -1107476636, -1107235870, -1106970675, -1106679239, -1106359654, -1106009912, -1105627904, -1105211414, + -1104758117, -1104265576, -1103731240, -1103152437, -1102526375, -1101850136, -1101120673, -1100334807, -1099489225, + -1098580473, -1097604958, -1096558943, -1095438542, -1094239723, -1092958302, -1091589944, -1090130161, -1088574313, + -1086917606, -1085155099, -1083281700, -1081292171, -1079181138, -1076943086, -1074572374, -1072063243, -1069409818, + -1066606126, -1063646105, -1060523618, -1057232468, -1053766415, -1050119192, -1046284528, -1042256165, -1038027882, + -1033593517, -1028946994, -1024082345, -1018993738, -1013675503, -1008122162, -1002328454, -996289366, -990000160, + -983456402, -976653990, -969589182, -962258626, -954659381, -946788949, -938645296, -930226877, -921532657, + -912562133, -903315354, -893792938, -883996084, -873926592, -863586870, -852979945, -842109472, -830979735, + -819595655, -807962787, -796087320, -783976072, -771636483, -759076610, -746305110, -733331233, -720164799, + -706816188, -693296313, -679616605, -665788980, -651825820, -637739943, -623544570, -609253297, -594880059, + -580439096, -565944918, -551412265, -536856066, -522291404, -507733472, -493197528, -478698857, -464252725, + -449874333, -435578778, -421381001, -407295749, -393337528, -379520558, -365858731, -352365567, -339054174, + -325937207, -313026827, -300334664, -287871784, -275648653, -263675105, -251960314, -240512770, -229340251, + -218449809, -207847746, -197539607, -187530166, -177823422, -168422593, -159330123, -150547678, -142076164, + -133915731, -126065794, -118525050, -111291498, -104362470, -97734652, -91404122, -85366377, -79616373, + -74148557, -68956911, -64034986, -59375949, -54972617, -50817502, -46902854, -43220698, -39762875, + -36521086, -33486923, -30651913, -28007548, -25545325, -23256770, -21133479, -19167136, -17349546, + -15672656, -14128580, -12709614, -11408260, -10217235, -9129491, -8138220, -7236869, -6419144, + -5679019, -5010736, -4408811, -3868031, -3383459, -2950426, -2564532, -2221640, -1917871, + -1649598, -1413439, -1206249, -1025112, -867332, -730423, -612103, -510279, -423042, + -348652, -285533, -232260, -187551, -150254, -119343, -93901, -73120, -56285, + -42770, -32029, -23588, -17037, -12025, -8254, -5472, -3467, -2064, + -1119, -513, -153 }; +RAM_ALIGN const Word32 LowDelayShapes_n960_N960_HRA_IP[1560] = { + 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, 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, 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, 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, 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, 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, 52, 175, 382, + 705, 1185, 1871, 2823, 4114, 5831, 8077, 10972, 14660, + 19303, 25092, 32244, 41009, 51670, 64545, 79996, 98427, 120290, + 146088, 176379, 211778, 252965, 300685, 355753, 419058, 491567, 574329, + 668476, 775231, 895906, 1031911, 1184750, 1356028, 1547453, 1760836, 1998091, + 2261242, 2552417, 2873848, 3227877, 3616948, 4043606, 4510498, 5020366, 5576047, + 6180463, 6836620, 7547602, 8316559, 9146706, 10041310, 11003683, 12037172, 13145144, + 14330983, 15598071, 16949778, 18389446, 19920381, 21545832, 23268982, 25092926, 27020662, + 29055072, 31198906, 33454766, 35825091, 38312140, 40917976, 43644450, 46493186, 49465569, + 52562726, 55785514, 59134509, 62609992, 66211939, 69940008, 73793535, 77771521, 81872629, + 86095178, 90437137, 94896125, 99469410, 104153908, 108946186, 113842469, 118838639, 123930249, + 129112527, 134380390, 139728454, 145151046, 150642225, 156195792, 161805313, 167464136, 173165413, + 178902121, 184667086, 190453005, 196252476, 202058015, 207862090, 213657145, 219435626, 225190009, + 230912827, 236596697, 242234348, 247818648, 253342624, 258799497, 264182697, 269485893, 274703012, + 279828312, 284856314, 289781856, 294600125, 299306665, 303897390, 308368599, 312716983, 316939635, + 321034059, 324998175, 328830319, 332529248, 336094136, 339524575, 342820570, 345982531, 349011267, + 351907976, 354674236, 357311989, 359823531, 362211496, 364478840, 366628822, 368664989, 370591159, + 372411396, 374129997, 375751467, 377280502, 378721970, 380080887, 381362400, 382571769, 383714343, + 384795547, 385820862, 386795806, 387725921, 388616754, 389473844, 390302710, 391108835, 391897652, + 392674541, 393444809, 394213686, 394986316, 395767747, 396562926, 397376691, 398213764, 399078748, + 399976120, 400910228, 401885285, 402905364, 403974398, 405096172, 406274322, 407512329, 408813519, + 410181054, 411617935, 413126993, 414710888, 416372104, 418112946, 419935539, 421841819, 423833534, + 425912241, 428079300, 430335872, 432682921, 435121205, 437651278, 440273491, 442987985, 445794697, + 448693355, 451683483, 454764399, 457935219, 461194860, 464542039, 467975283, 471492928, 475093126, + 478773851, 482532904, 486367920, 490276375, 494255591, 498302751, 502414896, 506588946, 510821698, + 515109841, 519449966, 523838572, 528272075, 532746823, 537259100, 541805139, 546381131, 550983233, + 555607579, 560250290, 564907481, 569575271, 574249791, 578927195, 583603665, 588275420, 592938724, + 597589893, 602225302, 606841390, 611434670, 616001729, 620539240, 625043960, 629512740, 633942527, + 638330370, 642673418, 646968929, 651214270, 655406919, 659544468, 663624624, 667645211, 671604169, + 675499557, 679329551, 683092449, 686786663, 690410727, 693963289, 697443117, 700849092, 704180212, + 707435589, 710614445, 713716116, 716740046, 719685788, 722553001, 725341451, 728051005, 730681634, + 733233409, 735706498, 738101168, 740417780, 742656787, 744818734, 746904257, 748914076, 750848997, + 752709910, 754497783, 756213660, 757858664, 759433984, 760940881, 762380680, 763754766, 765064584, + 766311629, 767497450, 768623637, 769691823, 770703677, 771660899, 772565218, 773418381, 774222155, + 774978320, 775688661, 776354967, 776979026, 777562617, 778107510, 778615459, 779088198, 779527438, + 779934863, 780312126, 780660846, 780982606, 781278948, 781551373, 781801337, 782030250, 782239474, + 782430322, 782604056, 782761888, 782904976, 783034427, 783151295, 783256582, 783351237, 783436158, + 783512191, 783580133, 783640729, 783694677, 783742630, 783785193, 783822926, 783856349, 783885939, + 783912134, 783935335, 783955909, 783974185, 783990464, 784005015, 784018080, 784029874, 784040589, + 784050394, 784059435, 784067843, 784075728, 784083188, 784090303, 784097145, 784103769, 784110225, + 784116552, 784122782, 784128939, 784135042, 784141107, 784147142, 784153152, 784159138, 784165118, + 784171086, 784177037, 784182968, 784188874, 784194749, 784200591, 784206393, 784212151, 784217862, + 784223520, 784229122, 784234663, 784240139, 784245546, 784250879, 784256136, 784261311, 784266402, + 784271403, 784276313, 784281126, 784285841, 784290452, 784294958, 784299354, 784303638, 784307807, + 784311858, 784315788, 784319595, 784323276, 784326828, 784330250, 784333539, 784336693, 784339710, + 784342589, 784345327, 784347923, 784350376, 784352685, 784354847, 784356862, 784358729, 784360447, + 784362016, 784363434, 784364702, 784365818, 784366783, 784367596, 784368257, 784368766, 784369124, + 784369331, 784369387, 784369292, 784369047, 784368653, 784368111, 784367421, 784366584, 784365602, + 784364475, 784363205, 784361793, 784360241, 784358550, 784356721, 784354756, 784352657, 784350426, + 784348065, 784345575, 784342958, 784340217, 784337354, 784334371, 784331270, 784328053, 784324723, + 784321282, 784317734, 784314079, 784310321, 784306463, 784302507, 784298456, 784294312, 784290078, + 784285758, 784281354, 784276869, 784272306, 784267667, 784262957, 784258177, 784253332, 784248423, + 784243454, 784238429, 784233349, 784228220, 784223043, 784217822, 784212560, 784207260, 784201926, + 784196560, 784191167, 784185749, 784180310, 784174852, 784169380, 784163896, 784158404, 784152907, + 784147408, 784141911, 784136419, 784130935, 784125463, 784120006, 784114567, 784109150, 784103757, + 784098392, 784093059, 784087760, 784082499, 784077278, 784072102, 784066974, 784061896, 784056872, + 784051904, 784046997, 784042152, 784037374, 784032665, 784028028, 784023466, 784018982, 784014580, + 784010261, 784006029, 784001887, 783997837, 783993883, 783990026, 783986270, 783982617, 783979069, + 783975630, 783972302, 783969087, 783965987, 783963005, 783960143, 783957404, 783954788, 783952300, + 783949939, 783947709, 783945612, 783943648, 783941820, 783940130, 783938578, 783937167, 783935898, + 783934772, 783933790, 783932954, 783932264, 783931722, 783931328, 783931084, 783930989, 783931045, + 783931251, 783931609, 783932118, 783932779, 783933592, 783934556, 783935672, 783936938, 783938356, + 783939924, 783941641, 783943507, 783945521, 783947682, 783949989, 783952441, 783955036, 783957773, + 783960650, 783963666, 783966818, 783970106, 783973526, 783977077, 783980756, 783984561, 783988490, + 783992539, 783996706, 784000989, 784005383, 784009887, 784014497, 784019210, 784024022, 784028930, + 784033930, 784039019, 784044193, 784049448, 784054780, 784060186, 784065661, 784071201, 784076801, + 784082459, 784088168, 784093926, 784099727, 784105568, 784111443, 784117348, 784123278, 784129229, + 784135197, 784141176, 784147163, 784153152, 784159138, 784165118, 784171086, 784177037, 784182968, + 784188874, 784194749, 784200591, 784206393, 784212151, 784217862, 784223520, 784229122, 784234663, + 784240139, 784245546, 784250879, 784256136, 784261311, 784266402, 784271403, 784276313, 784281126, + 784285841, 784290452, 784294958, 784299354, 784303638, 784307807, 784311858, 784315788, 784319595, + 784323276, 784326828, 784330250, 784333539, 784336693, 784339710, 784342589, 784345327, 784347923, + 784350376, 784352685, 784354847, 784356862, 784358729, 784360447, 784362016, 784363434, 784364702, + 784365818, 784366783, 784367596, 784368257, 784368766, 784369124, 784369331, 784369387, 784369292, + 784369047, 784368653, 784368111, 784367421, 784366584, 784365602, 784364475, 784363205, 784361793, + 784360241, 784358550, 784356721, 784354756, 784352657, 784350426, 784348065, 784345575, 784342958, + 784340217, 784337354, 784334371, 784331270, 784328053, 784324723, 784321282, 784317734, 784314079, + 784310321, 784306463, 784302507, 784298456, 784294312, 784290078, 784285758, 784281354, 784276869, + 784272306, 784267667, 784262957, 784258177, 784253332, 784248423, 784243454, 784238429, 784233349, + 784228220, 784223043, 784217822, 784212560, 784207260, 784201926, 784196560, 784191167, 784185749, + 784180310, 784174852, 784169380, 784163896, 784158404, 784152907, -784147408, -784141911, -784136419, + -784130935, -784125463, -784120006, -784114567, -784109150, -784103757, -784098392, -784093059, -784087760, + -784082499, -784077278, -784072102, -784066974, -784061896, -784056872, -784051904, -784046997, -784042152, + -784037374, -784032665, -784028028, -784023466, -784018982, -784014580, -784010261, -784006029, -784001887, + -783997837, -783993883, -783990026, -783986270, -783982617, -783979069, -783975630, -783972302, -783969087, + -783965987, -783963005, -783960143, -783957404, -783954788, -783952300, -783949939, -783947709, -783945612, + -783943648, -783941820, -783940130, -783938578, -783937167, -783935898, -783934772, -783933790, -783932954, + -783932264, -783931722, -783931328, -783931084, -783930989, -783931045, -783931251, -783931609, -783932118, + -783932779, -783933592, -783934556, -783935672, -783936938, -783938356, -783939924, -783941641, -783943507, + -783945521, -783947682, -783949989, -783952441, -783955036, -783957773, -783960650, -783963666, -783966818, + -783970106, -783973526, -783977077, -783980756, -783984561, -783988490, -783992539, -783996706, -784000989, + -784005383, -784009887, -784014497, -784019210, -784024022, -784028930, -784033930, -784039019, -784044193, + -784049448, -784054780, -784060186, -784065661, -784071201, -784076801, -784082459, -784088168, -784093926, + -784099727, -784105568, -784111443, -784117348, -784123278, -784129229, -784135197, -784141176, -784147163, + -784153152, -784159138, -784165118, -784171086, -784177037, -784182968, -784188874, -784194749, -784200591, + -784206393, -784212151, -784217862, -784223520, -784229122, -784234663, -784240139, -784245546, -784250879, + -784256136, -784261311, -784266402, -784271403, -784276313, -784281126, -784285841, -784290452, -784294958, + -784299354, -784303638, -784307807, -784311858, -784315788, -784319595, -784323276, -784326828, -784330250, + -784333539, -784336693, -784339710, -784342589, -784345327, -784347923, -784350376, -784352685, -784354847, + -784356862, -784358729, -784360447, -784362016, -784363434, -784364702, -784365818, -784366783, -784367596, + -784368257, -784368766, -784369124, -784369331, -784369387, -784369292, -784369047, -784368653, -784368111, + -784367421, -784366584, -784365602, -784364475, -784363205, -784361793, -784360241, -784358550, -784356721, + -784354756, -784352657, -784350426, -784348065, -784345575, -784342958, -784340217, -784337354, -784334371, + -784331270, -784328053, -784324723, -784321282, -784317734, -784314079, -784310321, -784306463, -784302507, + -784298456, -784294312, -784290078, -784285758, -784281354, -784276869, -784272306, -784267667, -784262957, + -784258177, -784253332, -784248423, -784243454, -784238429, -784233349, -784228220, -784223043, -784217822, + -784212560, -784207260, -784201926, -784196560, -784191167, -784185749, -784180310, -784174852, -784169380, + -784163896, -784158404, -784152907, -784147408, -784141911, -784136419, -784130935, -784125463, -784120006, + -784114567, -784109150, -784103757, -784098392, -784093059, -784087760, -784082499, -784077278, -784072102, + -784066974, -784061896, -784056872, -784051904, -784046997, -784042152, -784037374, -784032665, -784028028, + -784023466, -784018982, -784014580, -784010261, -784006029, -784001887, -783997837, -783993883, -783990026, + -783986270, -783982617, -783979069, -783975630, -783972302, -783969087, -783965987, -783963005, -783960143, + -783957404, -783954788, -783952300, -783949939, -783947709, -783945612, -783943648, -783941820, -783940130, + -783938578, -783937167, -783935898, -783934772, -783933790, -783932954, -783932264, -783931722, -783931328, + -783931084, -783930989, -783931045, -783931251, -783931609, -783932118, -783932779, -783933592, -783934556, + -783935672, -783936938, -783938356, -783939924, -783941641, -783943507, -783945521, -783947682, -783949989, + -783952441, -783955036, -783957773, -783960650, -783963666, -783966818, -783970106, -783973526, -783977077, + -783980756, -783984561, -783988490, -783992539, -783996706, -784000989, -784005383, -784009887, -784014497, + -784019210, -784024022, -784028930, -784033930, -784039019, -784044193, -784049448, -784054780, -784060186, + -784065661, -784071201, -784076801, -784082459, -784088168, -784093926, -784099727, -784105568, -784111443, + -784117348, -784123278, -784129229, -784135197, -784141176, -784147163, -784153131, -784159068, -784164963, + -784170795, -784176541, -784182173, -784187657, -784192951, -784198007, -784202769, -784207169, -784211130, + -784214559, -784217353, -784219391, -784220535, -784220630, -784219497, -784216937, -784212727, -784206617, + -784198327, -784187551, -784173947, -784157141, -784136723, -784112243, -784083213, -784049101, -784009333, + -783963287, -783910294, -783849634, -783780538, -783702180, -783613679, -783514100, -783402445, -783277658, + -783138617, -782984141, -782812977, -782623808, -782415247, -782185834, -781934039, -781658253, -781356794, + -781027899, -780669728, -780280356, -779857776, -779399894, -778904531, -778369419, -777792197, -777170416, + -776501532, -775782908, -775011810, -774185411, -773300787, -772354919, -771344691, -770266894, -769118226, + -767895293, -766594614, -765212620, -763745664, -762190019, -760541889, -758797411, -756952664, -755003678, + -752946440, -750776904, -748491005, -746084664, -743553805, -740894366, -738102311, -735173645, -732104432, + -728890802, -725528974, -722015270, -718346128, -714518120, -710527972, -706372573, -702048997, -697554517, + -692886621, -688043026, -683021694, -677820848, -672438982, -666874876, -661127608, -655196568, -649081463, + -642782332, -636299553, -629633851, -622786302, -615758346, -608551783, -601168786, -593611894, -585884022, + -577988458, -569928861, -561709265, -553334069, -544808041, -536136306, -527324347, -518377994, -509303418, + -500107123, -490795932, -481376983, -471857712, -462245842, -452549370, -442776550, -432935882, -423036090, + -413086109, -403095064, -393072251, -383027119, -372969246, -362908319, -352854112, -342816459, -332805234, + -322830326, -312901609, -303028921, -293222034, -283490629, -273844269, -264292369, -254844170, -245508712, + -236294804, -227211000, -218265568, -209466468, -200821323, -192337394, -184021561, -175880295, -167919639, + -160145191, -152562081, -145174961, -137987988, -131004813, -124228572, -117661879, -111306824, -105164969, + -99237348, -93524475, -88026347, -82742454, -77671790, -72812867, -68163733, -63721988, -59484805, + -55448955, -51610827, -47966456, -44511550, -41241516, -38151492, -35236370, -32490831, -29909374, + -27486341, -25215951, -23092326, -21109518, -19261540, -17542387, -15946062, -14466601, -13098096, + -11834709, -10670701, -9600439, -8618419, -7719279, -6897809, -6148962, -5467868, -4849835, + -4290361, -3785136, -3330046, -2921175, -2554807, -2227423, -1935704, -1676526, -1446955, + -1244248, -1065844, -909363, -772594, -653495, -550182, -460924, -384136, -318370, + -262309, -214759, -174641, -140984, -112917, -89663, -70531, -54908, -42257, + -32104, -24037, -17698, -12781, -9020, -6190, -4103, -2600, -1548, + -839, -385, -115 }; +#endif /* ENABLE_HR_MODE */ + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA_2_5ms[2] = { LowDelayShapes_n960_N480_HRA_2_5ms_IP, + LowDelayShapes_n960_N960_HRA_2_5ms_IP }; + +RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA_5ms[2] = { LowDelayShapes_n960_N480_HRA_5ms_IP, + LowDelayShapes_n960_N960_HRA_5ms_IP }; + +RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA[2] = { LowDelayShapes_n960_N480_HRA_IP, + LowDelayShapes_n960_N960_HRA_IP }; + +# ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA_7_5ms[2] = { LowDelayShapes_n960_N480_HRA_7_5ms_IP, + LowDelayShapes_n960_N960_HRA_7_5ms_IP }; +# endif +#endif /* ENABLE_HR_MODE */ + +RAM_ALIGN const Word16 pitch_max[5] = {MAX_PITCH_8K, MAX_PITCH_16K, MAX_PITCH_24K, MAX_PITCH_32K, MAX_PITCH_48K}; +RAM_ALIGN const Word16 plc_preemph_fac[NUM_SAMP_FREQ] = {20316, 23592, 26869, 30146, 30146 +# ifdef ENABLE_HR_MODE + , 30146 +# endif + }; +/* high pass filter Q15 */ +RAM_ALIGN const Word16 TDC_high_16[11] = {(Word16)0x0000, (Word16)0xfd60, (Word16)0xf7ab, (Word16)0xefec, + (Word16)0xe910, (Word16)0x66c2, (Word16)0xe910, (Word16)0xefec, + (Word16)0xf7ab, (Word16)0xfd60, (Word16)0x0000}; + +RAM_ALIGN const Word16 TDC_high_32[11] = {(Word16)0xf962, (Word16)0xf87d, (Word16)0xf581, (Word16)0xf2e5, + (Word16)0xf11a, (Word16)0x7076, (Word16)0xf11a, (Word16)0xf2e5, + (Word16)0xf581, (Word16)0xf87d, (Word16)0xf962}; + +RAM_ALIGN const Word16 TDC_high_16_harm[11] = {(Word16) 174, (Word16) 0, (Word16) -1442, (Word16) 0, + (Word16) 8641, (Word16) 18022, (Word16) 8641, (Word16) 0, + (Word16) -1442, (Word16) 0, (Word16) 174}; + +RAM_ALIGN const Word16 TDC_high_32_harm[11] = {(Word16) -174, (Word16) -121, (Word16) -459, (Word16) 590, + (Word16) 8743, (Word16) 16355, (Word16) 8743, (Word16) 590, + (Word16) -459, (Word16) -121, (Word16) -174}; + + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 LowDelayShapes_n960_N80[130] = { + -15, -43, -94, -171, -277, -414, -580, -771, -981, -1201, -1423, -1638, -1836, + -2008, -2145, -2240, -2286, -2279, -2214, -2085, -1889, -1621, -1274, -842, -318, 305, + 1034, 1876, 2833, 3906, 5091, 6379, 7754, 9198, 10683, 12179, 13652, 15068, 16390, + 17588, 18634, 19509, 20201, 20712, 21051, 21237, 21297, 21263, 21168, 21044, 20918, 20797, + 20701, 20627, 20571, 20529, 20499, 20479, 20468, 20463, 20464, 20469, 20477, 20486, 20495, + 20503, 20509, 20514, 20516, 20518, 20520, 20524, 20530, 20540, 20556, 20576, 20602, 20633, + 20668, 20705, -20743, -20781, -20816, -20847, -20873, -20894, -20910, -20920, -20927, -20930, -20932, + -20934, -20937, -20942, -20948, -20956, -20966, -20975, -20982, -20988, -20989, -20984, -20972, -20952, + -20921, -20879, -20822, -20747, -20652, -20532, -20359, -20121, -19785, -19318, -18689, -17873, -16855, + -15636, -14231, -12670, -10997, -9266, -7542, -5889, -4373, -3051, -1965, -1136, -560, -207}; +#else +#define LowDelayShapes_n960_N80 NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 LowDelayShapes_n960_N160[260] = { + -14, -29, -49, -76, -112, -156, -210, -275, -350, -437, -534, -641, -759, -885, + -1020, -1163, -1311, -1464, -1620, -1777, -1935, -2090, -2242, -2390, -2530, -2661, -2783, -2893, + -2990, -3073, -3140, -3191, -3224, -3238, -3233, -3208, -3162, -3094, -3003, -2889, -2751, -2587, + -2397, -2180, -1935, -1661, -1355, -1018, -648, -244, 197, 674, 1190, 1745, 2340, 2976, + 3652, 4370, 5129, 5928, 6766, 7642, 8553, 9496, 10470, 11469, 12490, 13529, 14579, 15637, + 16696, 17750, 18792, 19817, 20819, 21791, 22727, 23621, 24469, 25264, 26004, 26685, 27304, 27858, + 28348, 28773, 29134, 29433, 29672, 29855, 29986, 30070, 30112, 30117, 30092, 30043, 29976, 29895, + 29807, 29716, 29632, 29536, 29451, 29374, 29307, 29247, 29195, 29149, 29109, 29075, 29045, 29020, + 28999, 28982, 28968, 28957, 28949, 28943, 28940, 28939, 28940, 28942, 28946, 28950, 28956, 28962, + 28968, 28975, 28981, 28987, 28993, 28998, 29002, 29006, 29009, 29012, 29014, 29015, 29017, 29018, + 29019, 29021, 29024, 29027, 29031, 29037, 29044, 29053, 29064, 29077, 29091, 29108, 29126, 29146, + 29168, 29192, 29216, 29242, 29268, 29295, -29322, -29349, -29376, -29401, -29426, -29450, -29472, -29492, + -29511, -29527, -29542, -29555, -29566, -29575, -29583, -29589, -29593, -29596, -29599, -29601, -29602, -29603, + -29605, -29606, -29608, -29611, -29614, -29618, -29623, -29628, -29634, -29640, -29646, -29653, -29660, -29666, + -29671, -29676, -29680, -29682, -29683, -29682, -29678, -29673, -29664, -29653, -29639, -29621, -29600, -29574, + -29544, -29509, -29469, -29423, -29370, -29310, -29243, -29167, -29083, -28988, -28861, -28718, -28551, -28351, + -28114, -27834, -27505, -27121, -26677, -26168, -25591, -24943, -24223, -23431, -22569, -21639, -20644, -19592, + -18487, -17338, -16154, -14944, -13719, -12491, -11270, -10068, -8898, -7771, -6698, -5689, -4753, -3898, + -3130, -2452, -1866, -1371, -964, -640, -392, -198}; +#else +#define LowDelayShapes_n960_N160 NULL +#endif +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 LowDelayShapes_n960_N240[390] = { + -9, -17, -26, -37, -50, -66, -86, -108, -134, -164, -197, -234, -275, -320, + -369, -422, -479, -539, -603, -670, -741, -814, -891, -969, -1050, -1132, -1216, -1301, + -1387, -1473, -1558, -1643, -1728, -1810, -1892, -1971, -2047, -2120, -2190, -2256, -2318, -2376, + -2429, -2477, -2519, -2556, -2586, -2611, -2629, -2640, -2645, -2642, -2632, -2614, -2589, -2556, + -2515, -2466, -2408, -2341, -2266, -2182, -2088, -1985, -1872, -1748, -1615, -1471, -1316, -1150, + -972, -783, -582, -368, -141, 99, 352, 619, 899, 1194, 1503, 1827, 2166, 2519, + 2888, 3271, 3669, 4082, 4510, 4952, 5408, 5878, 6362, 6857, 7365, 7885, 8414, 8954, + 9502, 10058, 10621, 11189, 11761, 12335, 12912, 13488, 14063, 14635, 15203, 15764, 16319, 16864, + 17399, 17922, 18431, 18926, 19405, 19866, 20309, 20732, 21135, 21517, 21876, 22213, 22526, 22817, + 23083, 23326, 23546, 23743, 23916, 24068, 24198, 24308, 24397, 24469, 24522, 24560, 24582, 24592, + 24589, 24575, 24552, 24522, 24485, 24443, 24398, 24349, 24300, 24252, 24209, 24155, 24104, 24058, + 24014, 23974, 23938, 23904, 23873, 23844, 23818, 23794, 23773, 23753, 23735, 23719, 23705, 23692, + 23681, 23670, 23662, 23654, 23647, 23642, 23638, 23634, 23632, 23630, 23629, 23629, 23629, 23630, + 23632, 23634, 23636, 23639, 23642, 23645, 23648, 23652, 23655, 23658, 23662, 23665, 23669, 23672, + 23674, 23677, 23680, 23682, 23684, 23686, 23687, 23688, 23689, 23690, 23691, 23692, 23693, 23693, + 23694, 23695, 23696, 23697, 23699, 23701, 23703, 23706, 23710, 23714, 23718, 23723, 23729, 23736, + 23743, 23751, 23760, 23769, 23779, 23790, 23801, 23813, 23825, 23838, 23851, 23865, 23879, 23894, + 23908, 23923, -23938, -23952, -23967, -23981, -23996, -24010, -24023, -24036, -24049, -24061, -24072, -24083, + -24093, -24102, -24111, -24119, -24127, -24133, -24139, -24145, -24149, -24153, -24157, -24160, -24162, -24164, + -24166, -24167, -24168, -24169, -24170, -24171, -24171, -24172, -24173, -24174, -24175, -24176, -24178, -24179, + -24181, -24184, -24186, -24189, -24192, -24195, -24198, -24202, -24205, -24209, -24213, -24216, -24219, -24223, + -24226, -24228, -24231, -24233, -24234, -24235, -24236, -24236, -24235, -24233, -24230, -24227, -24222, -24217, + -24210, -24202, -24193, -24183, -24171, -24158, -24143, -24127, -24109, -24089, -24067, -24043, -24017, -23988, + -23957, -23923, -23886, -23847, -23804, -23758, -23708, -23655, -23584, -23509, -23427, -23336, -23234, -23119, + -22990, -22846, -22685, -22506, -22307, -22087, -21845, -21580, -21291, -20977, -20638, -20272, -19880, -19462, + -19018, -18549, -18054, -17536, -16995, -16432, -15849, -15248, -14630, -13997, -13353, -12698, -12036, -11369, + -10700, -10032, -9367, -8709, -8059, -7422, -6800, -6196, -5611, -5050, -4513, -4004, -3523, -3073, + -2655, -2269, -1917, -1598, -1312, -1059, -837, -646, -484, -350, -239, -127}; +#else +#define LowDelayShapes_n960_N240 NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 LowDelayShapes_n960_N320[520] = { + -6, -12, -17, -23, -30, -39, -48, -60, -72, -86, -102, -119, -138, -159, + -182, -207, -234, -262, -293, -325, -359, -396, -434, -473, -515, -558, -603, -649, + -697, -746, -797, -848, -900, -954, -1008, -1062, -1118, -1173, -1229, -1285, -1340, -1396, + -1451, -1505, -1559, -1612, -1664, -1715, -1764, -1813, -1859, -1904, -1947, -1988, -2027, -2064, + -2098, -2130, -2159, -2186, -2210, -2230, -2248, -2263, -2275, -2283, -2289, -2290, -2289, -2283, + -2274, -2262, -2245, -2225, -2201, -2173, -2141, -2105, -2065, -2020, -1971, -1918, -1860, -1797, + -1730, -1658, -1582, -1500, -1414, -1322, -1225, -1122, -1014, -901, -782, -657, -526, -389, + -246, -97, 59, 221, 390, 565, 748, 937, 1133, 1336, 1547, 1764, 1989, 2221, + 2460, 2707, 2961, 3222, 3490, 3765, 4048, 4338, 4634, 4937, 5246, 5562, 5884, 6212, + 6546, 6885, 7229, 7578, 7932, 8289, 8650, 9014, 9382, 9751, 10123, 10496, 10870, 11244, + 11619, 11992, 12365, 12736, 13105, 13471, 13833, 14192, 14546, 14895, 15239, 15576, 15907, 16231, + 16547, 16856, 17155, 17446, 17727, 17999, 18261, 18512, 18753, 18983, 19202, 19409, 19605, 19790, + 19963, 20125, 20275, 20414, 20541, 20658, 20764, 20858, 20943, 21017, 21082, 21137, 21184, 21221, + 21251, 21273, 21287, 21295, 21297, 21293, 21285, 21271, 21254, 21233, 21209, 21182, 21154, 21124, + 21092, 21060, 21028, 20999, 20972, 20935, 20902, 20870, 20839, 20811, 20784, 20758, 20734, 20712, + 20691, 20671, 20653, 20635, 20619, 20604, 20590, 20577, 20565, 20554, 20543, 20534, 20525, 20517, + 20509, 20502, 20496, 20491, 20486, 20481, 20477, 20474, 20471, 20469, 20467, 20465, 20464, 20464, + 20463, 20463, 20463, 20464, 20465, 20466, 20467, 20468, 20470, 20472, 20474, 20476, 20478, 20480, + 20482, 20485, 20487, 20489, 20491, 20494, 20496, 20498, 20500, 20502, 20504, 20505, 20507, 20508, + 20510, 20511, 20512, 20513, 20514, 20515, 20516, 20516, 20517, 20517, 20518, 20518, 20519, 20519, + 20519, 20520, 20521, 20521, 20522, 20523, 20524, 20526, 20527, 20529, 20531, 20533, 20536, 20539, + 20542, 20546, 20549, 20554, 20558, 20563, 20568, 20573, 20579, 20586, 20592, 20599, 20606, 20613, + 20621, 20629, 20637, 20646, 20655, 20663, 20672, 20682, 20691, 20700, 20710, 20720, -20729, -20739, + -20748, -20758, -20767, -20776, -20785, -20794, -20803, -20812, -20820, -20828, -20836, -20843, -20851, -20857, + -20864, -20870, -20876, -20882, -20887, -20892, -20896, -20901, -20905, -20908, -20911, -20914, -20917, -20919, + -20921, -20923, -20925, -20926, -20927, -20928, -20929, -20930, -20931, -20931, -20932, -20932, -20933, -20933, + -20934, -20934, -20935, -20935, -20936, -20937, -20938, -20939, -20940, -20941, -20943, -20944, -20946, -20947, + -20949, -20951, -20953, -20955, -20958, -20960, -20962, -20964, -20967, -20969, -20971, -20974, -20976, -20978, + -20980, -20982, -20983, -20985, -20986, -20987, -20988, -20989, -20989, -20989, -20988, -20988, -20986, -20985, + -20983, -20980, -20978, -20974, -20970, -20966, -20961, -20955, -20949, -20942, -20934, -20926, -20917, -20907, + -20896, -20885, -20873, -20859, -20845, -20830, -20814, -20796, -20778, -20758, -20737, -20714, -20690, -20665, + -20638, -20610, -20580, -20548, -20515, -20480, -20433, -20384, -20333, -20279, -20220, -20155, -20085, -20008, + -19924, -19833, -19734, -19627, -19511, -19385, -19249, -19103, -18946, -18778, -18598, -18406, -18202, -17986, + -17757, -17515, -17260, -16993, -16713, -16421, -16116, -15799, -15470, -15129, -14778, -14415, -14043, -13661, + -13271, -12872, -12466, -12053, -11634, -11210, -10782, -10351, -9918, -9484, -9049, -8616, -8184, -7755, + -7330, -6910, -6496, -6090, -5691, -5301, -4922, -4553, -4196, -3852, -3521, -3204, -2902, -2615, + -2343, -2087, -1847, -1624, -1417, -1226, -1051, -892, -748, -619, -504, -404, -316, -241, + -175, -92}; +#else +#define LowDelayShapes_n960_N320 NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 LowDelayShapes_n960_N480[780] = { + -4, -8, -11, -13, -16, -20, -24, -28, -33, -38, -44, -50, -57, -64, + -72, -81, -90, -100, -110, -121, -133, -146, -159, -173, -187, -202, -218, -235, + -252, -270, -289, -308, -328, -349, -370, -392, -415, -438, -462, -486, -511, -537, + -563, -589, -616, -643, -671, -699, -728, -757, -786, -815, -845, -875, -905, -935, + -965, -996, -1026, -1056, -1087, -1117, -1147, -1177, -1207, -1236, -1266, -1295, -1323, -1352, + -1380, -1407, -1434, -1461, -1486, -1512, -1537, -1561, -1584, -1607, -1629, -1650, -1670, -1690, + -1709, -1726, -1743, -1759, -1774, -1788, -1801, -1813, -1824, -1834, -1842, -1850, -1856, -1861, + -1865, -1868, -1870, -1870, -1869, -1867, -1863, -1858, -1852, -1845, -1836, -1826, -1814, -1801, + -1786, -1770, -1753, -1734, -1713, -1691, -1668, -1643, -1616, -1588, -1558, -1527, -1494, -1459, + -1422, -1384, -1344, -1302, -1259, -1213, -1166, -1117, -1066, -1013, -959, -902, -843, -783, + -720, -655, -588, -519, -448, -374, -299, -221, -141, -58, 27, 114, 203, 295, + 389, 486, 585, 687, 791, 898, 1007, 1119, 1234, 1351, 1471, 1593, 1718, 1846, + 1976, 2109, 2244, 2382, 2523, 2667, 2813, 2961, 3113, 3266, 3423, 3582, 3743, 3907, + 4073, 4241, 4412, 4585, 4760, 4938, 5117, 5299, 5483, 5668, 5855, 6045, 6235, 6428, + 6622, 6817, 7013, 7211, 7410, 7610, 7811, 8012, 8215, 8417, 8621, 8824, 9028, 9232, + 9436, 9639, 9843, 10045, 10248, 10449, 10650, 10850, 11048, 11246, 11442, 11636, 11829, 12020, + 12209, 12396, 12581, 12763, 12944, 13121, 13296, 13468, 13638, 13804, 13967, 14127, 14284, 14437, + 14586, 14732, 14875, 15014, 15148, 15280, 15407, 15530, 15649, 15764, 15875, 15981, 16084, 16183, + 16277, 16367, 16453, 16535, 16612, 16686, 16755, 16821, 16882, 16940, 16993, 17043, 17089, 17131, + 17170, 17205, 17237, 17265, 17291, 17313, 17331, 17348, 17361, 17371, 17379, 17385, 17388, 17389, + 17388, 17385, 17380, 17374, 17366, 17356, 17345, 17333, 17320, 17306, 17292, 17276, 17260, 17243, + 17226, 17209, 17191, 17174, 17157, 17142, 17128, 17108, 17089, 17071, 17053, 17036, 17019, 17003, + 16988, 16973, 16959, 16946, 16933, 16920, 16908, 16897, 16886, 16875, 16865, 16856, 16846, 16838, + 16829, 16821, 16814, 16806, 16799, 16793, 16786, 16780, 16775, 16769, 16764, 16759, 16755, 16751, + 16747, 16743, 16739, 16736, 16733, 16730, 16727, 16725, 16722, 16720, 16718, 16717, 16715, 16714, + 16712, 16711, 16711, 16710, 16709, 16709, 16708, 16708, 16708, 16708, 16708, 16708, 16709, 16709, + 16710, 16710, 16711, 16712, 16713, 16714, 16715, 16716, 16717, 16718, 16719, 16720, 16721, 16722, + 16724, 16725, 16726, 16727, 16728, 16730, 16731, 16732, 16733, 16734, 16736, 16737, 16738, 16739, + 16740, 16741, 16742, 16743, 16744, 16744, 16745, 16746, 16747, 16747, 16748, 16748, 16749, 16750, + 16750, 16750, 16751, 16751, 16751, 16752, 16752, 16752, 16753, 16753, 16753, 16753, 16753, 16754, + 16754, 16754, 16755, 16755, 16755, 16756, 16756, 16757, 16757, 16758, 16759, 16759, 16760, 16761, + 16762, 16763, 16765, 16766, 16767, 16769, 16770, 16772, 16774, 16776, 16778, 16780, 16782, 16785, + 16787, 16790, 16793, 16796, 16799, 16802, 16805, 16809, 16812, 16816, 16820, 16824, 16828, 16832, + 16836, 16840, 16845, 16849, 16854, 16858, 16863, 16868, 16873, 16878, 16883, 16888, 16893, 16898, + 16903, 16908, 16914, 16919, -16924, -16929, -16934, -16940, -16945, -16950, -16955, -16960, -16965, -16970, + -16975, -16980, -16984, -16989, -16994, -16998, -17003, -17007, -17011, -17015, -17020, -17023, -17027, -17031, + -17035, -17038, -17041, -17045, -17048, -17051, -17053, -17056, -17059, -17061, -17064, -17066, -17068, -17070, + -17072, -17074, -17075, -17077, -17078, -17080, -17081, -17082, -17083, -17084, -17085, -17086, -17086, -17087, + -17088, -17088, -17089, -17089, -17089, -17090, -17090, -17090, -17091, -17091, -17091, -17091, -17092, -17092, + -17092, -17092, -17093, -17093, -17093, -17094, -17094, -17094, -17095, -17095, -17096, -17097, -17097, -17098, + -17099, -17099, -17100, -17101, -17102, -17103, -17104, -17105, -17106, -17107, -17108, -17109, -17110, -17111, + -17113, -17114, -17115, -17116, -17118, -17119, -17120, -17121, -17123, -17124, -17125, -17126, -17127, -17129, + -17130, -17131, -17132, -17133, -17133, -17134, -17135, -17136, -17136, -17137, -17137, -17137, -17137, -17137, + -17137, -17137, -17137, -17136, -17136, -17135, -17134, -17133, -17132, -17130, -17129, -17127, -17125, -17123, + -17120, -17118, -17115, -17112, -17109, -17105, -17102, -17098, -17094, -17089, -17085, -17080, -17075, -17069, + -17063, -17057, -17051, -17044, -17037, -17030, -17022, -17014, -17005, -16997, -16987, -16978, -16967, -16957, + -16946, -16934, -16922, -16910, -16897, -16883, -16869, -16855, -16840, -16824, -16808, -16791, -16773, -16755, + -16736, -16717, -16690, -16663, -16637, -16609, -16581, -16550, -16518, -16484, -16448, -16409, -16369, -16326, + -16280, -16232, -16181, -16127, -16070, -16010, -15947, -15880, -15810, -15736, -15658, -15577, -15491, -15402, + -15308, -15210, -15108, -15001, -14890, -14775, -14655, -14530, -14401, -14267, -14128, -13985, -13837, -13685, + -13528, -13367, -13201, -13030, -12855, -12676, -12493, -12306, -12114, -11919, -11720, -11517, -11311, -11102, + -10889, -10674, -10455, -10234, -10010, -9784, -9556, -9327, -9095, -8862, -8628, -8393, -8157, -7921, + -7684, -7448, -7211, -6976, -6741, -6507, -6274, -6042, -5813, -5585, -5360, -5137, -4917, -4700, + -4487, -4276, -4070, -3867, -3668, -3474, -3284, -3099, -2919, -2744, -2574, -2410, -2251, -2097, + -1949, -1807, -1671, -1540, -1415, -1297, -1184, -1077, -976, -881, -791, -707, -629, -556, + -489, -427, -369, -317, -269, -226, -188, -151, -114, -59}; +#else +#define LowDelayShapes_n960_N480 NULL +#endif + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 LowDelayShapes_n960_N40_5ms[70] = { + 29, 112, 280, 563, 991, 1590, 2380, 3377, 4587, 6006, 7624, 9416, 11353, 13393, + 15490, 17595, 19657, 21624, 23450, 25092, 26519, 27707, 28645, 29332, 29783, 30021, 30083, 30008, + 29840, 29625, 29408, 29214, 29077, 28993, 28956, 28961, 29000, 29068, 29156, 29256, -29361, -29462, + -29551, -29620, -29661, -29666, -29628, -29542, -29403, -29209, -28923, -28521, -27962, -27210, -26234, -25014, + -23541, -21819, -19874, -17743, -15481, -13149, -10820, -8571, -6479, -4611, -3020, -1753, -842, -284}; +#else +#define LowDelayShapes_n960_N40_5ms NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 LowDelayShapes_n960_N80_5ms[140] = { + 13, 31, 60, 102, 161, 239, 339, 464, 615, 795, 1006, 1251, 1530, 1845, + 2198, 2588, 3015, 3481, 3983, 4520, 5092, 5697, 6331, 6992, 7677, 8382, 9104, 9838, + 10580, 11326, 12071, 12811, 13540, 14255, 14951, 15624, 16270, 16885, 17466, 18010, 18515, 18978, + 19399, 19775, 20106, 20393, 20636, 20836, 20995, 21115, 21199, 21250, 21271, 21266, 21239, 21194, + 21134, 21064, 20987, 20908, 20836, 20757, 20688, 20630, 20581, 20542, 20513, 20491, 20478, 20473, + 20475, 20483, 20497, 20517, 20541, 20568, 20600, 20633, 20669, 20706, -20743, -20780, -20816, -20850, + -20881, -20910, -20934, -20954, -20968, -20977, -20979, -20973, -20960, -20938, -20908, -20868, -20819, -20761, + -20692, -20613, -20508, -20389, -20248, -20080, -19883, -19653, -19387, -19083, -18738, -18351, -17920, -17444, + -16923, -16358, -15749, -15099, -14410, -13687, -12933, -12154, -11353, -10537, -9712, -8884, -8060, -7246, + -6450, -5679, -4938, -4235, -3574, -2959, -2397, -1889, -1441, -1055, -732, -474, -277, -138}; +#else +#define LowDelayShapes_n960_N80_5ms NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 LowDelayShapes_n960_N120_5ms[210] = { + 9, 17, 28, 44, 65, 91, 123, 161, 208, 262, 325, 398, 480, 572, + 676, 791, 918, 1057, 1209, 1374, 1552, 1744, 1950, 2169, 2402, 2648, 2908, 3181, + 3468, 3767, 4078, 4402, 4736, 5081, 5437, 5801, 6174, 6554, 6942, 7335, 7732, 8134, + 8538, 8943, 9349, 9755, 10159, 10560, 10957, 11349, 11735, 12114, 12485, 12846, 13198, 13539, + 13868, 14184, 14487, 14776, 15051, 15311, 15555, 15784, 15997, 16194, 16374, 16538, 16686, 16818, + 16935, 17036, 17123, 17195, 17254, 17299, 17333, 17355, 17366, 17368, 17361, 17347, 17325, 17297, + 17265, 17228, 17189, 17147, 17104, 17061, 17024, 16979, 16938, 16901, 16867, 16837, 16811, 16788, + 16768, 16752, 16739, 16729, 16722, 16718, 16716, 16717, 16720, 16726, 16734, 16743, 16755, 16768, + 16782, 16798, 16815, 16833, 16852, 16871, 16891, 16911, -16931, -16952, -16972, -16991, -17010, -17028, + -17045, -17061, -17076, -17090, -17101, -17111, -17119, -17125, -17128, -17129, -17127, -17123, -17116, -17106, + -17092, -17076, -17056, -17033, -17006, -16976, -16942, -16905, -16864, -16820, -16760, -16698, -16630, -16553, + -16467, -16370, -16263, -16144, -16013, -15868, -15710, -15537, -15349, -15146, -14927, -14693, -14442, -14175, + -13891, -13591, -13276, -12944, -12597, -12236, -11862, -11474, -11074, -10664, -10244, -9816, -9380, -8938, + -8492, -8043, -7592, -7141, -6692, -6247, -5807, -5374, -4949, -4534, -4131, -3741, -3365, -3005, + -2662, -2337, -2030, -1744, -1478, -1234, -1012, -814, -638, -486, -357, -250, -164, -95}; +#else +#define LowDelayShapes_n960_N120_5ms NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 LowDelayShapes_n960_N160_5ms[280] = { + 13, 23, 36, 52, 73, 98, 128, 163, 205, 253, 308, 371, 441, 520, + 608, 705, 812, 929, 1056, 1195, 1344, 1505, 1678, 1863, 2060, 2270, 2493, 2729, + 2978, 3241, 3516, 3805, 4108, 4424, 4753, 5095, 5450, 5818, 6198, 6591, 6995, 7411, + 7839, 8277, 8725, 9184, 9651, 10128, 10612, 11104, 11603, 12108, 12618, 13133, 13653, 14175, + 14700, 15226, 15754, 16281, 16808, 17334, 17857, 18376, 18892, 19403, 19909, 20408, 20901, 21385, + 21861, 22328, 22784, 23231, 23666, 24089, 24500, 24898, 25283, 25654, 26011, 26354, 26681, 26994, + 27291, 27572, 27838, 28089, 28323, 28541, 28744, 28931, 29103, 29259, 29401, 29528, 29640, 29738, + 29823, 29895, 29955, 30002, 30038, 30063, 30078, 30083, 30080, 30068, 30049, 30023, 29991, 29953, + 29911, 29865, 29815, 29763, 29708, 29653, 29597, 29541, 29496, 29437, 29381, 29329, 29280, 29235, + 29194, 29156, 29122, 29091, 29064, 29039, 29018, 29000, 28986, 28974, 28964, 28958, 28954, 28953, + 28954, 28958, 28964, 28972, 28982, 28994, 29007, 29023, 29040, 29058, 29078, 29099, 29121, 29144, + 29168, 29192, 29218, 29243, 29269, 29295, -29322, -29348, -29374, -29400, -29425, -29450, -29474, -29498, + -29520, -29541, -29561, -29580, -29597, -29613, -29627, -29639, -29649, -29657, -29663, -29667, -29668, -29667, + -29663, -29657, -29647, -29635, -29620, -29602, -29580, -29556, -29528, -29496, -29462, -29424, -29382, -29337, + -29288, -29236, -29181, -29122, -29041, -28964, -28880, -28788, -28688, -28579, -28460, -28332, -28193, -28042, + -27879, -27705, -27517, -27315, -27100, -26871, -26627, -26369, -26095, -25806, -25501, -25180, -24844, -24492, + -24123, -23739, -23339, -22924, -22493, -22048, -21588, -21114, -20627, -20128, -19616, -19094, -18561, -18018, + -17467, -16907, -16341, -15769, -15192, -14611, -14028, -13442, -12857, -12272, -11689, -11109, -10533, -9963, + -9400, -8846, -8300, -7765, -7241, -6730, -6232, -5749, -5282, -4830, -4396, -3979, -3581, -3202, + -2843, -2505, -2188, -1893, -1620, -1369, -1141, -936, -753, -593, -454, -336, -237, -155}; +#else +#define LowDelayShapes_n960_N160_5ms NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 LowDelayShapes_n960_N240_5ms[420] = { + 10, 15, 21, 27, 36, 45, 56, 69, 83, 100, 118, 138, 161, 186, + 214, 244, 276, 312, 350, 392, 436, 484, 535, 590, 648, 710, 775, 845, + 918, 995, 1076, 1162, 1252, 1346, 1444, 1547, 1655, 1767, 1883, 2005, 2131, 2261, + 2397, 2537, 2683, 2833, 2988, 3148, 3312, 3482, 3656, 3835, 4019, 4208, 4401, 4599, + 4801, 5008, 5220, 5436, 5656, 5880, 6109, 6342, 6578, 6818, 7063, 7310, 7562, 7816, + 8074, 8335, 8598, 8865, 9134, 9405, 9679, 9955, 10233, 10513, 10794, 11076, 11360, 11645, + 11931, 12217, 12504, 12791, 13078, 13366, 13652, 13939, 14224, 14509, 14792, 15075, 15356, 15635, + 15912, 16187, 16460, 16731, 16999, 17264, 17526, 17785, 18041, 18293, 18542, 18787, 19028, 19264, + 19497, 19725, 19949, 20168, 20382, 20592, 20796, 20996, 21190, 21379, 21563, 21741, 21914, 22082, + 22243, 22399, 22550, 22695, 22834, 22967, 23095, 23216, 23332, 23443, 23548, 23647, 23740, 23828, + 23910, 23987, 24059, 24125, 24186, 24243, 24294, 24340, 24381, 24418, 24450, 24478, 24502, 24522, + 24537, 24549, 24557, 24562, 24563, 24561, 24556, 24549, 24538, 24525, 24510, 24492, 24473, 24451, + 24428, 24404, 24378, 24351, 24323, 24294, 24264, 24234, 24204, 24173, 24143, 24112, 24093, 24059, + 24027, 23997, 23968, 23940, 23914, 23889, 23865, 23842, 23821, 23801, 23783, 23765, 23749, 23734, + 23720, 23708, 23696, 23686, 23677, 23668, 23661, 23655, 23650, 23647, 23644, 23641, 23640, 23640, + 23641, 23642, 23645, 23648, 23652, 23657, 23662, 23668, 23675, 23682, 23691, 23699, 23708, 23718, + 23728, 23739, 23750, 23762, 23774, 23786, 23799, 23812, 23825, 23839, 23853, 23866, 23881, 23895, + 23909, 23923, -23938, -23952, -23966, -23980, -23994, -24008, -24022, -24036, -24049, -24062, -24075, -24088, + -24100, -24112, -24123, -24134, -24144, -24154, -24164, -24173, -24181, -24189, -24195, -24202, -24207, -24212, + -24216, -24219, -24222, -24223, -24224, -24224, -24223, -24221, -24218, -24214, -24208, -24202, -24195, -24187, + -24177, -24167, -24155, -24142, -24128, -24113, -24097, -24079, -24060, -24040, -24019, -23996, -23972, -23947, + -23921, -23893, -23864, -23834, -23802, -23769, -23721, -23681, -23638, -23592, -23543, -23492, -23438, -23380, + -23319, -23255, -23186, -23115, -23039, -22959, -22875, -22786, -22693, -22596, -22494, -22387, -22275, -22157, + -22035, -21908, -21775, -21637, -21494, -21345, -21190, -21030, -20864, -20692, -20515, -20332, -20143, -19948, + -19748, -19541, -19329, -19112, -18888, -18659, -18425, -18185, -17940, -17690, -17434, -17174, -16909, -16639, + -16365, -16087, -15804, -15518, -15228, -14934, -14637, -14337, -14034, -13728, -13420, -13109, -12797, -12483, + -12167, -11851, -11533, -11215, -10896, -10577, -10258, -9940, -9623, -9307, -8992, -8678, -8367, -8058, + -7752, -7448, -7148, -6851, -6557, -6268, -5983, -5702, -5426, -5156, -4890, -4630, -4375, -4126, + -3884, -3647, -3417, -3194, -2977, -2767, -2565, -2369, -2181, -2001, -1829, -1664, -1507, -1358, + -1218, -1085, -961, -846, -738, -639, -547, -464, -388, -320, -259, -206, -159, -124}; +#else +#define LowDelayShapes_n960_N240_5ms NULL +#endif + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 LowDelayShapes_n960_N40_2_5ms[40] = { + 140, 566, 1277, 2319, 3704, 5404, 7357, 9466, 11616, 13686, 15563, 17163, 18436, 19375, + 20007, 20391, 20594, 20685, 20717, 20724, -20724, -20717, -20685, -20594, -20391, -20007, -19375, -18436, + -17163, -15563, -13686, -11616, -9466, -7357, -5404, -3704, -2319, -1277, -566, -140}; +#else +#define LowDelayShapes_n960_N40_2_5ms NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 LowDelayShapes_n960_N80_2_5ms[80] = { + 140, 353, 653, 1049, 1553, 2171, 2909, 3768, 4747, 5842, 7043, 8341, 9721, 11165, + 12655, 14170, 15688, 17188, 18649, 20051, 21376, 22610, 23739, 24756, 25656, 26436, 27099, 27650, + 28097, 28450, 28721, 28922, 29065, 29164, 29228, 29267, 29290, 29301, 29306, 29308, -29308, -29306, + -29301, -29290, -29267, -29228, -29164, -29065, -28922, -28721, -28450, -28097, -27650, -27099, -26436, -25656, + -24756, -23739, -22610, -21376, -20051, -18649, -17188, -15688, -14170, -12655, -11165, -9721, -8341, -7043, + -5842, -4747, -3768, -2909, -2171, -1553, -1049, -653, -353, -140}; +#else +#define LowDelayShapes_n960_N80_2_5ms NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 LowDelayShapes_n960_N120_2_5ms[120] = { + 93, 196, 328, 491, 689, 924, 1199, 1514, 1873, 2274, 2720, 3209, 3742, 4318, + 4934, 5588, 6277, 7000, 7750, 8526, 9321, 10132, 10953, 11780, 12606, 13427, 14237, 15032, + 15807, 16557, 17278, 17967, 18620, 19234, 19809, 20341, 20830, 21276, 21680, 22040, 22360, 22641, + 22884, 23092, 23269, 23416, 23538, 23636, 23714, 23775, 23822, 23857, 23882, 23900, 23913, 23920, + 23925, 23928, 23930, 23930, -23930, -23930, -23928, -23925, -23920, -23913, -23900, -23882, -23857, -23822, + -23775, -23714, -23636, -23538, -23416, -23269, -23092, -22884, -22641, -22360, -22040, -21680, -21276, -20830, + -20341, -19809, -19234, -18620, -17967, -17278, -16557, -15807, -15032, -14237, -13427, -12606, -11780, -10953, + -10132, -9321, -8526, -7750, -7000, -6277, -5588, -4934, -4318, -3742, -3209, -2720, -2274, -1873, + -1514, -1199, -924, -689, -491, -328, -196, -93}; +#else +#define LowDelayShapes_n960_N120_2_5ms NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 LowDelayShapes_n960_N160_2_5ms[160] = { + 70, 134, 210, 301, 407, 530, 671, 830, 1008, 1206, 1425, 1665, 1926, 2208, + 2512, 2837, 3183, 3550, 3937, 4343, 4768, 5211, 5670, 6143, 6631, 7131, 7642, 8161, + 8688, 9219, 9755, 10292, 10828, 11363, 11893, 12417, 12933, 13440, 13936, 14418, 14887, 15339, + 15775, 16193, 16593, 16972, 17332, 17670, 17988, 18285, 18561, 18816, 19050, 19264, 19459, 19635, + 19793, 19934, 20059, 20168, 20264, 20347, 20418, 20478, 20529, 20572, 20606, 20635, 20657, 20675, + 20689, 20700, 20708, 20713, 20718, 20720, 20722, 20723, 20724, 20724, -20724, -20724, -20723, -20722, + -20720, -20718, -20713, -20708, -20700, -20689, -20675, -20657, -20635, -20606, -20572, -20529, -20478, -20418, + -20347, -20264, -20168, -20059, -19934, -19793, -19635, -19459, -19264, -19050, -18816, -18561, -18285, -17988, + -17670, -17332, -16972, -16593, -16193, -15775, -15339, -14887, -14418, -13936, -13440, -12933, -12417, -11893, + -11363, -10828, -10292, -9755, -9219, -8688, -8161, -7642, -7131, -6631, -6143, -5670, -5211, -4768, + -4343, -3937, -3550, -3183, -2837, -2512, -2208, -1926, -1665, -1425, -1206, -1008, -830, -671, + -530, -407, -301, -210, -134, -70}; +#else +#define LowDelayShapes_n960_N160_2_5ms NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 LowDelayShapes_n960_N240_2_5ms[240] = { + 47, 81, 118, 160, 207, 259, 317, 381, 452, 528, 611, 701, 799, 903, + 1015, 1134, 1260, 1395, 1537, 1686, 1844, 2009, 2183, 2363, 2552, 2748, 2951, 3162, + 3380, 3604, 3836, 4073, 4317, 4567, 4822, 5083, 5348, 5618, 5892, 6170, 6451, 6735, + 7022, 7311, 7601, 7892, 8185, 8477, 8769, 9060, 9350, 9639, 9926, 10209, 10491, 10768, + 11042, 11312, 11577, 11837, 12092, 12341, 12585, 12822, 13053, 13277, 13494, 13705, 13908, 14103, + 14291, 14472, 14645, 14810, 14968, 15118, 15261, 15396, 15523, 15643, 15756, 15862, 15961, 16054, + 16140, 16220, 16293, 16361, 16424, 16481, 16533, 16580, 16623, 16662, 16697, 16728, 16755, 16780, + 16802, 16821, 16837, 16851, 16864, 16874, 16883, 16891, 16897, 16902, 16907, 16910, 16913, 16915, + 16917, 16918, 16919, 16920, 16921, 16921, 16921, 16921, -16921, -16921, -16921, -16921, -16920, -16919, + -16918, -16917, -16915, -16913, -16910, -16907, -16902, -16897, -16891, -16883, -16874, -16864, -16851, -16837, + -16821, -16802, -16780, -16755, -16728, -16697, -16662, -16623, -16580, -16533, -16481, -16424, -16361, -16293, + -16220, -16140, -16054, -15961, -15862, -15756, -15643, -15523, -15396, -15261, -15118, -14968, -14810, -14645, + -14472, -14291, -14103, -13908, -13705, -13494, -13277, -13053, -12822, -12585, -12341, -12092, -11837, -11577, + -11312, -11042, -10768, -10491, -10209, -9926, -9639, -9350, -9060, -8769, -8477, -8185, -7892, -7601, + -7311, -7022, -6735, -6451, -6170, -5892, -5618, -5348, -5083, -4822, -4567, -4317, -4073, -3836, + -3604, -3380, -3162, -2951, -2748, -2552, -2363, -2183, -2009, -1844, -1686, -1537, -1395, -1260, + -1134, -1015, -903, -799, -701, -611, -528, -452, -381, -317, -259, -207, -160, -118, + -81, -47}; +#else +#define LowDelayShapes_n960_N240_2_5ms NULL +#endif + + +#ifdef SUBSET_NB +RAM_ALIGN const Word32 lag_win_8k[16] = {0x7fdba30b, 0x7f6eca1a, 0x7eba2e4e, 0x7dbf01e8, 0x7c7eecec, 0x7afc0879, + 0x7938d8eb, 0x773846e0, 0x74fd973a, 0x728c623e, 0x6fe889ee, 0x6d162fc8, + 0x6a19aa0b, 0x66f778a7, 0x63b43a09, 0x60549fe1}; +#else +#define lag_win_8k NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word32 lag_win_16k[16] = {0x7ff6e7cb, 0x7fdba30b, 0x7fae3d5f, 0x7f6eca1a, 0x7f1d643a, 0x7eba2e4e, + 0x7e455264, 0x7dbf01e8, 0x7d277581, 0x7c7eecec, 0x7bc5aecb, 0x7afc0879, + 0x7a224dcf, 0x7938d8eb, 0x784009f7, 0x773846e0}; +#else +#define lag_win_16k NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word32 lag_win_24k[16] = {0x7ffbf529, 0x7fefd569, 0x7fdba30b, 0x7fbf61e2, 0x7f9b1748, 0x7f6eca1a, + 0x7f3a82b8, 0x7efe4b00, 0x7eba2e4e, 0x7e6e3976, 0x7e1a7ac1, 0x7dbf01e8, + 0x7d5be00f, 0x7cf127c2, 0x7c7eecec, 0x7c0544d0}; +#else +#define lag_win_24k NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word32 lag_win_32k[16] = {0x7ffdb9e3, 0x7ff6e7cb, 0x7feb8a70, 0x7fdba30b, 0x7fc7334b, 0x7fae3d5f, + 0x7f90c3ed, 0x7f6eca1a, 0x7f485382, 0x7f1d643a, 0x7eee00d1, 0x7eba2e4e, + 0x7e81f22e, 0x7e455264, 0x7e045558, 0x7dbf01e8}; +#else +#define lag_win_32k NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word32 lag_win_48k[16] = {0x7ffefd47, 0x7ffbf529, 0x7ff6e7cb, 0x7fefd569, 0x7fe6be59, 0x7fdba30b, + 0x7fce8403, 0x7fbf61e2, 0x7fae3d5f, 0x7f9b1748, 0x7f85f087, 0x7f6eca1a, + 0x7f55a51b, 0x7f3a82b8, 0x7f1d643a, 0x7efe4b00}; +#else +#define lag_win_48k NULL +#endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 lag_win_96k[16] = {0x7fffbf52, 0x7ffefd47, 0x7ffdb9e3, 0x7ffbf529, 0x7ff9af1f, 0x7ff6e7cb, + 0x7ff39f35, 0x7fefd569, 0x7feb8a70, 0x7fe6be59, 0x7fe17132, 0x7fdba30b, + 0x7fd553f5, 0x7fce8403, 0x7fc7334b, 0x7fbf61e2}; +# else +# define lag_win_96k NULL +# endif + +RAM_ALIGN const Word32 *const lag_win[NUM_SAMP_FREQ] = {lag_win_8k, lag_win_16k, lag_win_24k, lag_win_32k, lag_win_48k, lag_win_96k}; + +RAM_ALIGN const Word16 sqrt_table_phecu[49] = {/* used by Sqrt_l */ + 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}; + +/* First frequency bin in each subband now adjusted to include last bin * + * which was missed with the previous definition * + * 250 750 1250 2250 4250 8250 12250 16250 20250 ( 24250 ) * + * note that bins over 20000 are zeroed and not used */ +/* [- FB ----------------------------) (Currently limited to 20kHz) + * [- SWB -----------------------) + * [- sWB -------------------) + * [- WB ----------------) + * [- NB -----------) + */ + +RAM_ALIGN const Word16 gw_len_inv_shift_fx[MAX_LGW] = {/* Q0 */ + 1 - 1 /*/1/2*/, 1 - 1, 2 - 1 /*1/4*/, + 3 - 1 /*1/8*/, 4 - 1 /*1/16*/, 4 - 1, + 4 - 1, 4 - 1, 4 - 1}; +RAM_ALIGN const Word16 gwlpr_fx[MAX_LGW + 1] = { + 1, + 3 * QUOT_LPR_LTR, + 5 * QUOT_LPR_LTR, + 9 * QUOT_LPR_LTR, + 17 * QUOT_LPR_LTR, + 33 * QUOT_LPR_LTR, + 49 * QUOT_LPR_LTR, + 65 * QUOT_LPR_LTR, + 81 * QUOT_LPR_LTR, + 97 * QUOT_LPR_LTR}; /* frequency group start bins for transient analysis */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING + /* puretone_ana compressed ATH bandborder weights */ +RAM_ALIGN const Word16 scATHFx[MAX_LGW - 2] = { 14924 , 30499 , 31886 , 32767 , 29770 , 25417 , 16384 }; + /* 0.455444335937500 0.930755615234375 0.973083496093750 0.999969482421875 0.908508300781250 0.775665283203125 0.5*/ +#endif + +RAM_ALIGN const Word16 e_tot_headroom[5] = {3, 3, 4, 4, 4}; /* smallest head room to use for each fs */ + + + +RAM_ALIGN const Word16 xfp_wE_MDCT2FFTQ11[5] = {4077, 8283, 12489, 16698, + 25109}; /* Q11 Mantissa of scale to use for each fs */ + +RAM_ALIGN const Word16 POW_ATT_TABLE0[OFF_FRAMES_LIMIT + 1] = { + 32767, 31293, 29885, 28540, 27255, 26029, 24857, 23738, 22670, 21650, 20675, 19745, 18856, 18007, 17197, 16423, + 8211, 4106, 2053, 1026, 513, 257, 128, 64, 32, 16, 8, 4, 2, 1, 0}; +RAM_ALIGN const Word16 POW_ATT_TABLE1[OFF_FRAMES_LIMIT + 1] = { + 32767, 31656, 30581, 29543, 28540, 27571, 26635, 25731, 24857, 24013, 23198, 22410, 21650, 20915, 20205, 19519, + 9759, 4880, 2440, 1220, 610, 305, 152, 76, 38, 19, 10, 5, 2, 1, 0}; + +#ifdef PLC2_FADEOUT_IN_MS +#if PLC2_FADEOUT_IN_MS == 0 +#ifndef CR8_A_PLC_FADEOUT_TUNING +/*/ default setting only requieres two tables */ +RAM_ALIGN const Word16 *const POW_ATT_TABLES[1 + 2] = { + NULL, + POW_ATT_TABLE1 /*1 0.3dB steps */, + POW_ATT_TABLE0 /*2 0.4 dB steps*/, +}; +#endif + +#else /* PLC2_FADEOUT_IN_MS == 0 */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING +RAM_ALIGN const Word16 POW_ATT_TABLE_p3x9_14_7[OFF_FRAMES_LIMIT + 1] = { + 32767, + 31656, 30581, 29543, 28540, 27571, 26635, 25731, 24857, 24013, /* 9 times .3dB steps , 14 6 dB steps, 7 muted steps */ + 12007, 6003, 3002, 1501, 750, 375, 188, 94, 47, 23, 12, 6, 3, 1, + 0, 0, 0, 0, 0, 0, 0 }; + +RAM_ALIGN const Word16 POW_ATT_TABLE_p4x9_14_7[OFF_FRAMES_LIMIT + 1] = +{ 32767, + 31293, 29885, 28540, 27255, 26029, 24857, 23738, 22670, 21650, /* 9 times .4dB steps , 14 6 dB steps, 7 muted steps */ + 10825, 5413, 2706, 1353, 677, 338, 169, 85, 42, 21, 11, 5, 3, 1, + 0, 0,0,0,0,0,0 }; +#endif + +RAM_ALIGN const Word16 POW_ATT_TABLE_p3x8_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 31656, 30581, 29543, 28540, 27571, 26635, 25731, 12865, 6433, 3216, 1608, 804, 402, 201, 101, + 50, 25, 13, 6, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0}; +RAM_ALIGN const Word16 POW_ATT_TABLE_p4x8_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 31293, 29885, 28540, 27255, 26029, 24857, 23738, 11869, 5935, 2967, 1484, 742, 371, 185, 93, + 46, 23, 12, 6, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; + +RAM_ALIGN const Word16 POW_ATT_TABLE_p3x4_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 31656, 30581, 29543, 14772, 7386, 3693, 1847, 923, 462, 231, 115, 58, 29, 14, 7, + 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +RAM_ALIGN const Word16 POW_ATT_TABLE_p4x4_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 31293, 29885, 28540, 14270, 7135, 3568, 1784, 892, 446, 223, 111, 56, 28, 14, 7, + 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +RAM_ALIGN const Word16 POW_ATT_TABLE_p3x2_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 31656, 15828, 7914, 3957, 1979, 989, 495, 247, 124, 62, 31, 15, 8, 4, 2, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +RAM_ALIGN const Word16 POW_ATT_TABLE_p4x2_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 31293, 15647, 7823, 3912, 1956, 978, 489, 244, 122, 61, 31, 15, 8, 4, 2, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +RAM_ALIGN const Word16 POW_ATT_TABLE_p3x1_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +RAM_ALIGN const Word16 POW_ATT_TABLE_p4x1_6[OFF_FRAMES_LIMIT + 1] = { + 32767, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +#ifdef CR8_A_PLC_FADEOUT_TUNING +/* POW_ATT_TABLES now ordered logically based on initial slow muting phase time */ +/* POW_ATT_TABLES[ind] is used after teh initial gain==1.0 no energy muting phase */ +RAM_ALIGN const Word16 *const POW_ATT_TABLES[1 + 24 / 2] = +{ NULL, +/*0.3dB col , 0.4dB col */ +/* 1*/POW_ATT_TABLE_p3x1_6, POW_ATT_TABLE_p4x1_6, /* 0 0.3dB, 16 6dB, 14mute */ /* 0.4dB version */ /* old short mute tabs */ +/* 3*/POW_ATT_TABLE_p3x2_6, POW_ATT_TABLE_p4x2_6, /* 1 0.3dB, 15 6dB ,14mute */ /* 0.4dB version */ +/* 5*/POW_ATT_TABLE_p3x4_6, POW_ATT_TABLE_p4x4_6, /* 3 0.3dB, 15 6dB , 12 mute */ /* 0.4dB version */ +/* 7*/POW_ATT_TABLE_p3x8_6, POW_ATT_TABLE_p4x8_6, /* 7 0.3dB, 15 6dB , 8 mute */ /* 0.4dB version */ +/* 9*/POW_ATT_TABLE_p3x9_14_7, POW_ATT_TABLE_p4x9_14_7, /* 9 0.3dB, 14 6dB , 7 mute */ /* 0.4dB version */ /* opt 120 ms */ +/*11*/POW_ATT_TABLE1, POW_ATT_TABLE0, /* 15 0.3dB, 14 6dB , 1 mute */ /* 0.4dB version */ /* 3GPP original/default curves */ +}; + +/* PLC_FADEOUT_TUNING, extended table nominal muting phases from 30 ms to 140 ms */ +RAM_ALIGN const Word16 fade_scheme_tab_fx[24 / 2][3] = { +/* burst_att_thresh indicates when muting POW_ATT_TABLE[att_per_frame_idx] should be used first time it is 1.0 though */ +/* burst_att_thresh ==2 --> gains [ 1.0, 32767/32768.0(first table value used) , first muted, .... ]*/ +/* burst_att_thresh ==5 --> gains [ 1.0, 1.0, 1,0 1,0, 32767/32768.0(first table value used) , first muted,... ]*/ +/* beta_mute_thr ==4 --> start of final attenuation attenuate AvgMix */ + +/* tabled {att_per_frame_idx_p3dB , burst_att_thresh, beta_mute_thr } */ +{ 1, 2, 0 + 2 + 2 }, /* 30 ms, 0.3 dB delta att in slow mutephase nominal_fadeout=0 */ +{ 1, 3, 0 + 3 + 2 }, /* 40 ms, 0.3 dB delta att in slow mutephase */ +{ 3, 3, 1 + 3 + 1 }, /* 50 ms, 0.3 dB delta att in slow mutephase */ +{ 3, 4, 1 + 4 + 1}, /* 60 ms, 0.3 dB delta att in slow mutephase */ +{ 5, 4, 3 + 4 + 1 }, /* 70 ms, 0.3 dB delta att in slow mutephase */ +{ 5, 5, 3 + 5 + 1 }, /* 80 ms, 0.3 dB delta att in slow mutephase */ +{ 7, 5, 7 + 5 }, /* 90 ms, 0.3 dB delta att in slow mutephase */ +{ 7, 5, 7 + 5 + 1}, /* 100 ms, 0.3 dB delta att in slow mutephase */ +{ 9, 5, 9 + 5 }, /* 110 ms, 0.3 dB delta att in slow mutephase */ +{ 9, 5, 9 + 5 + 1}, /* 120 ms, 0.3 dB delta att in slow mutephase nominal_fadeout=1 */ +{ 11, 5, 15 + 5 },/* 130 ms, 0.3 dB delta att in slow mutephase */ +{ 11, 6, 15 + 6 },/* 140 ms, 0.3 dB delta att in slow mutephase nominal 3GPP */ +}; +/*fade_scheme_tab_fx[ind][0] att_per _fram_index , "points" to first column in POW_ATT TABLES */ +/*fade_scheme_tab_fx[ind][1] is burst_att_thresh, the number of non_muted 1.0 gain frames */ +/*fade_scheme_tab_fx[ind][2] is beta_mute_thr, the location of the start of final attenuation */ + +#else +RAM_ALIGN const Word16 *const POW_ATT_TABLES[1 + 10] = { + NULL, + POW_ATT_TABLE1, + POW_ATT_TABLE0, + /* .3dB x16,16 6dB steps */ /* .4dB x16, 16 6dB steps */ /*original/default */ + POW_ATT_TABLE_p3x8_6, + POW_ATT_TABLE_p4x8_6, + /* .3dB x8, 24 6dB steps */ /* .4dB x8, 24 6dB steps */ + POW_ATT_TABLE_p3x4_6, + POW_ATT_TABLE_p4x4_6, + /* .3dB x4, 28 6dB steps */ /* .4dB x4, 28 6dB steps */ + POW_ATT_TABLE_p3x2_6, + POW_ATT_TABLE_p4x2_6, + /* .3dB x2, 30 6dB steps */ /* .4dB x2, 30 6dB steps */ + POW_ATT_TABLE_p3x1_6, + POW_ATT_TABLE_p4x1_6 /* .3dB x1, 30 6dB steps */ /* .4dB x1, 30 6dB steps */ +}; +#endif + +#endif /* PLC2_FADEOUT_IN_MS == 0 */ + +#else /* PLC2_FADEOUT_IN_MS */ +RAM_ALIGN const Word16 *const POW_ATT_TABLES[1 + 2] = { + NULL, + POW_ATT_TABLE1 /*1 .3dB steps */, + POW_ATT_TABLE0 /*2 .4 dB steps*/, +}; +#endif /* PLC2_FADEOUT_IN_MS */ + +RAM_ALIGN const Word16 sin_quarterQ15_fx[256 + 1] = { + 0, 201, 402, 603, 804, 1005, 1206, 1407, 1608, 1809, 2009, 2210, 2411, 2611, 2811, 3012, + 3212, 3412, 3612, 3812, 4011, 4211, 4410, 4609, 4808, 5007, 5205, 5404, 5602, 5800, 5998, 6195, + 6393, 6590, 6787, 6983, 7180, 7376, 7571, 7767, 7962, 8157, 8351, 8546, 8740, 8933, 9127, 9319, + 9512, 9704, 9896, 10088, 10279, 10469, 10660, 10850, 11039, 11228, 11417, 11605, 11793, 11980, 12167, 12354, + 12540, 12725, 12910, 13095, 13279, 13463, 13646, 13828, 14010, 14192, 14373, 14553, 14733, 14912, 15091, 15269, + 15447, 15624, 15800, 15976, 16151, 16326, 16500, 16673, 16846, 17018, 17190, 17361, 17531, 17700, 17869, 18037, + 18205, 18372, 18538, 18703, 18868, 19032, 19195, 19358, 19520, 19681, 19841, 20001, 20160, 20318, 20475, 20632, + 20788, 20943, 21097, 21251, 21403, 21555, 21706, 21856, 22006, 22154, 22302, 22449, 22595, 22740, 22884, 23028, + 23170, 23312, 23453, 23593, 23732, 23870, 24008, 24144, 24279, 24414, 24548, 24680, 24812, 24943, 25073, 25202, + 25330, 25457, 25583, 25708, 25833, 25956, 26078, 26199, 26320, 26439, 26557, 26674, 26791, 26906, 27020, 27133, + 27246, 27357, 27467, 27576, 27684, 27791, 27897, 28002, 28106, 28209, 28311, 28411, 28511, 28610, 28707, 28803, + 28899, 28993, 29086, 29178, 29269, 29359, 29448, 29535, 29622, 29707, 29792, 29875, 29957, 30038, 30118, 30196, + 30274, 30350, 30425, 30499, 30572, 30644, 30715, 30784, 30853, 30920, 30986, 31050, 31114, 31177, 31238, 31298, + 31357, 31415, 31471, 31527, 31581, 31634, 31686, 31737, 31786, 31834, 31881, 31927, 31972, 32015, 32058, 32099, + 32138, 32177, 32214, 32251, 32286, 32319, 32352, 32383, 32413, 32442, 32470, 32496, 32522, 32546, 32568, 32590, + 32610, 32629, 32647, 32664, 32679, 32693, 32706, 32718, 32729, 32738, 32746, 32753, 32758, 32762, 32766, 32767, + 32767}; + +/* 16 ms tables for PHECU fft windowing and post ifft preTda MDCT windowing (window 11) */ +/* 3+3ms tapering for the hamming parts */ +/* temporary ROM solution */ +/* alternatively use values from a single 48 kHz table */ + +/* 3ms rising tapering part @48 kHZ */ +/* only quarter sine hamming part is actually used by the C-function windowing_fx */ +/* OPT: store only one table at 48 or 96 kHz */ +/* OPT2: for this to work one must switch to 'periodic' instead of used 'symetric' windows, * + * the different windows are just sub-sampled windows of a 96kHz window */ + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 PhECU_whr16ms_NB_Q15[Lprot_hamm_len2_8k] = {/* From matlab */ + 2621, 2750, 3135, 3769, 4641, 5736, + 7036, 8519, 10158, 11926, 13793, 15727, + 17695, 19662, 21596, 23463, 25231, 26871, + 28353, 29653, 30749, 31621, 32254, 32639}; +#else +#define PhECU_whr16ms_NB_Q15 NULL +#endif +#ifdef SUBSET_WB +RAM_ALIGN const Word16 PhECU_whr16ms_WB_Q15[Lprot_hamm_len2_16k] = {/* From matlab */ + 2621, 2654, 2750, 2911, 3135, 3421, 3769, + 4176, 4641, 5162, 5736, 6362, 7036, 7756, + 8519, 9320, 10158, 11028, 11926, 12850, 13793, + 14754, 15727, 16709, 17695, 18681, 19662, 20635, + 21596, 22540, 23463, 24361, 25231, 26069, 26871, + 27633, 28353, 29027, 29653, 30228, 30749, 31214, + 31621, 31968, 32254, 32478, 32639, 32736}; +#else +#define PhECU_whr16ms_WB_Q15 NULL +#endif +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 PhECU_whr16ms_sWB_Q15[Lprot_hamm_len2_24k] = + {/* From matlab */ + 2621, 2636, 2679, 2750, 2850, 2979, 3135, 3319, 3530, 3769, 4034, 4325, 4641, 4982, 5347, + 5736, 6148, 6582, 7036, 7511, 8006, 8519, 9049, 9596, 10158, 10735, 11324, 11926, 12539, 13162, + 13793, 14432, 15077, 15727, 16381, 17037, 17695, 18352, 19008, 19662, 20312, 20957, 21596, 22227, 22850, + 23463, 24065, 24655, 25231, 25794, 26340, 26871, 27384, 27878, 28353, 28808, 29242, 29653, 30042, 30407, + 30749, 31065, 31356, 31621, 31859, 32070, 32254, 32411, 32539, 32639, 32711, 32754}; +#else +#define PhECU_whr16ms_sWB_Q15 NULL +#endif +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 PhECU_whr16ms_SWB_Q15[Lprot_hamm_len2_32k] = + {/* From matlab */ + 2621, 2630, 2654, 2694, 2750, 2823, 2911, 3015, 3135, 3270, 3421, 3588, 3769, 3965, 4176, 4401, + 4641, 4894, 5162, 5442, 5736, 6043, 6362, 6693, 7036, 7391, 7756, 8132, 8519, 8915, 9320, 9735, + 10158, 10589, 11028, 11474, 11926, 12385, 12850, 13319, 13793, 14272, 14754, 15239, 15727, 16217, 16709, 17202, + 17695, 18188, 18681, 19172, 19662, 20150, 20635, 21118, 21596, 22070, 22540, 23004, 23463, 23916, 24361, 24800, + 25231, 25654, 26069, 26475, 26871, 27257, 27633, 27999, 28353, 28696, 29027, 29347, 29653, 29947, 30228, 30495, + 30749, 30988, 31214, 31424, 31621, 31802, 31968, 32119, 32254, 32374, 32478, 32567, 32639, 32695, 32736, 32760}; +#else +#define PhECU_whr16ms_SWB_Q15 NULL +#endif +#ifdef SUBSET_FB +RAM_ALIGN const Word16 PhECU_whr16ms_FB_Q15[Lprot_hamm_len2_48k] = + {/* From matlab */ + 2621, 2625, 2636, 2654, 2679, 2711, 2750, 2797, 2850, 2911, 2979, 3053, 3135, 3224, 3319, 3421, + 3530, 3646, 3769, 3898, 4034, 4176, 4325, 4480, 4641, 4808, 4982, 5162, 5347, 5539, 5736, 5939, + 6148, 6362, 6582, 6806, 7036, 7271, 7511, 7756, 8006, 8260, 8519, 8782, 9049, 9320, 9596, 9875, + 10158, 10445, 10735, 11028, 11324, 11624, 11926, 12232, 12539, 12850, 13162, 13477, 13793, 14112, 14432, 14754, + 15077, 15402, 15727, 16054, 16381, 16709, 17037, 17366, 17695, 18024, 18352, 18681, 19008, 19336, 19662, 19988, + 20312, 20635, 20957, 21277, 21596, 21913, 22227, 22540, 22850, 23158, 23463, 23765, 24065, 24361, 24655, 24945, + 25231, 25514, 25794, 26069, 26340, 26608, 26871, 27129, 27384, 27633, 27878, 28118, 28353, 28583, 28808, 29027, + 29242, 29450, 29653, 29850, 30042, 30228, 30407, 30581, 30749, 30910, 31065, 31214, 31356, 31491, 31621, 31743, + 31859, 31968, 32070, 32166, 32254, 32336, 32411, 32478, 32539, 32593, 32639, 32678, 32711, 32736, 32754, 32764}; +#else +#define PhECU_whr16ms_FB_Q15 NULL +#endif + +/* initial 2ms for preTda is the LD-MDCT analysis window times the centered inverse whr window */ +#ifdef SUBSET_NB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_128_pre_Q14[16] = {-12, -34, -74, -135, -219, -327, -459, -610, + -776, -949, -1125, -1295, -1451, -1587, -1696, -1771}; +#else +#define PhECU_preTdaFx16ms_128_pre_Q14 NULL +#endif +#ifdef SUBSET_WB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_256_pre_Q14[32] = { + -8, -16, -27, -42, -63, -87, -117, -154, -196, -244, -299, -358, -424, -495, -570, -650, + -733, -818, -906, -993, -1082, -1168, -1253, -1336, -1414, -1488, -1556, -1617, -1671, -1718, -1755, -1784}; +#else +#define PhECU_preTdaFx16ms_256_pre_Q14 NULL +#endif +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_384_pre_Q14[48] = { + -6, -12, -18, -25, -34, -45, -59, -74, -92, -112, -135, -160, -188, -219, -253, -289, + -328, -369, -413, -459, -507, -557, -610, -663, -719, -775, -833, -891, -950, -1008, -1067, -1125, + -1183, -1239, -1295, -1349, -1401, -1451, -1499, -1545, -1587, -1627, -1663, -1696, -1725, -1750, -1771, -1788}; +#else +#define PhECU_preTdaFx16ms_384_pre_Q14 NULL +#endif +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_512_pre_Q14[64] = { + -5, -9, -13, -18, -24, -31, -38, -47, -57, -68, -81, -94, -109, -126, -144, -164, + -185, -207, -232, -257, -284, -313, -343, -374, -407, -441, -477, -513, -551, -590, -630, -670, + -712, -754, -797, -840, -884, -927, -972, -1016, -1059, -1104, -1147, -1190, -1232, -1274, -1316, -1356, + -1395, -1433, -1470, -1505, -1539, -1572, -1602, -1632, -1659, -1684, -1707, -1728, -1747, -1763, -1777, -1789}; +#else +#define PhECU_preTdaFx16ms_512_pre_Q14 NULL +#endif +#ifdef SUBSET_FB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_768_pre_Q14[96] = { + -4, -8, -11, -13, -15, -19, -23, -27, -32, -37, -43, -48, -55, -62, -70, -78, + -87, -97, -107, -117, -129, -141, -154, -168, -181, -196, -211, -228, -244, -261, -280, -298, + -318, -338, -358, -380, -402, -424, -447, -471, -495, -520, -545, -570, -596, -623, -650, -677, + -705, -733, -761, -789, -818, -847, -876, -905, -934, -964, -993, -1022, -1052, -1082, -1111, -1140, + -1169, -1197, -1226, -1254, -1281, -1309, -1336, -1362, -1388, -1415, -1439, -1464, -1488, -1511, -1534, -1556, + -1577, -1598, -1617, -1636, -1655, -1671, -1688, -1703, -1718, -1731, -1744, -1755, -1766, -1776, -1784, -1791}; +#else +#define PhECU_preTdaFx16ms_768_pre_Q14 NULL +#endif + +/* ROM OPT compute it runtime based on MDCT win and tabled inverse hamming sections */ +/* 16 ms tables for PHECU fft windowing and post ifft preTda MDCT windowing */ +/* OPT2 can be reduced to 14.25 ms, due to 1.75 ms trailing zeroes */ +#ifdef SUBSET_NB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_NB_Q14[128] = { + -22591, -21465, -18295, -14331, -10544, -7321, -4690, -2561, -811, 662, 1942, 3090, 4148, 5146, 6107, 7043, + 7961, 8868, 9761, 10640, 11502, 12345, 13164, 13959, 14731, 15423, 15970, 16374, 16642, 16789, 16837, 16810, + 16735, 16637, 16537, 16441, 16366, 16307, 16263, 16230, 16206, 16190, 16181, 16177, 16178, 16182, 16188, 16196, + 16203, 16209, 16214, 16218, 16219, 16221, 16222, 16226, 16230, 16238, 16251, 16267, 16287, 16312, 16339, 16369, + 16399, 16429, 16456, 16481, 16502, 16518, 16531, 16539, 16544, 16547, 16548, 16550, 16552, 16556, 16561, 16567, + 16575, 16582, 16588, 16592, 16593, 16589, 16580, 16564, 16540, 16506, 16461, 16402, 16327, 16232, 16095, 15907, + 15641, 15272, 14775, 14130, 13325, 12361, 11251, 10017, 8694, 7354, 6057, 4825, 3684, 2665, 1795, 1095, + 575, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#else +#define PhECU_preTdaFx16ms_NB_Q14 NULL +#endif +#ifdef SUBSET_WB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_WB_Q14[256] = { + -22528, -22351, -21532, -20186, -18475, -16565, -14596, -12673, -10858, -9181, -7654, -6277, -5037, -3923, -2914, + -2001, -1169, -405, 303, 961, 1580, 2166, 2725, 3263, 3781, 4285, 4778, 5262, 5739, 6211, + 6677, 7140, 7601, 8059, 8514, 8968, 9419, 9868, 10314, 10756, 11195, 11630, 12060, 12486, 12907, + 13322, 13733, 14137, 14537, 14917, 15263, 15573, 15847, 16085, 16286, 16454, 16587, 16689, 16763, 16810, + 16833, 16836, 16822, 16795, 16757, 16712, 16663, 16612, 16565, 16511, 16464, 16421, 16383, 16350, 16321, + 16295, 16272, 16253, 16237, 16223, 16211, 16201, 16194, 16187, 16183, 16180, 16178, 16177, 16178, 16179, + 16181, 16184, 16187, 16190, 16194, 16198, 16201, 16204, 16208, 16210, 16213, 16215, 16217, 16218, 16219, + 16220, 16221, 16222, 16222, 16223, 16225, 16227, 16229, 16232, 16236, 16241, 16247, 16255, 16262, 16272, + 16282, 16293, 16305, 16319, 16332, 16347, 16361, 16376, 16391, 16407, 16422, 16436, 16450, 16463, 16475, + 16487, 16497, 16506, 16514, 16522, 16528, 16533, 16537, 16541, 16543, 16545, 16546, 16547, 16548, 16549, + 16550, 16550, 16551, 16553, 16555, 16557, 16560, 16563, 16566, 16569, 16573, 16577, 16580, 16584, 16587, + 16589, 16592, 16593, 16593, 16593, 16591, 16588, 16583, 16577, 16569, 16559, 16547, 16532, 16516, 16496, + 16474, 16448, 16418, 16385, 16347, 16305, 16258, 16205, 16134, 16054, 15960, 15849, 15716, 15560, 15376, + 15161, 14913, 14628, 14306, 13944, 13541, 13098, 12616, 12097, 11540, 10952, 10335, 9692, 9030, 8362, + 7699, 7045, 6400, 5769, 5155, 4560, 3990, 3448, 2936, 2460, 2022, 1625, 1272, 963, 700, + 481, 306, 161, 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}; +#else +#define PhECU_preTdaFx16ms_WB_Q14 NULL +#endif +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_sWB_Q14[384] = { + -22499, -22471, -22152, -21551, -20715, -19688, -18527, -17277, -15982, -14679, -13393, -12145, -10954, -9826, + -8760, -7763, -6831, -5958, -5149, -4394, -3688, -3029, -2410, -1831, -1285, -769, -279, 186, + 630, 1055, 1462, 1856, 2236, 2606, 2966, 3317, 3662, 3999, 4330, 4658, 4981, 5301, + 5618, 5933, 6246, 6556, 6866, 7175, 7481, 7788, 8093, 8398, 8702, 9004, 9306, 9606, + 9906, 10205, 10502, 10798, 11092, 11385, 11676, 11965, 12252, 12537, 12820, 13101, 13379, 13655, + 13929, 14200, 14470, 14732, 14977, 15208, 15422, 15622, 15804, 15970, 16121, 16256, 16374, 16478, + 16567, 16643, 16703, 16753, 16789, 16815, 16830, 16837, 16835, 16825, 16810, 16789, 16764, 16735, + 16704, 16671, 16637, 16604, 16575, 16538, 16503, 16471, 16441, 16414, 16389, 16366, 16345, 16325, + 16307, 16291, 16276, 16263, 16250, 16239, 16230, 16221, 16213, 16206, 16200, 16195, 16190, 16187, + 16184, 16181, 16180, 16178, 16178, 16178, 16178, 16178, 16180, 16181, 16182, 16185, 16187, 16189, + 16191, 16193, 16195, 16198, 16200, 16202, 16205, 16207, 16208, 16211, 16213, 16214, 16215, 16217, + 16217, 16218, 16219, 16219, 16220, 16221, 16221, 16221, 16222, 16223, 16224, 16224, 16226, 16227, + 16228, 16230, 16233, 16236, 16239, 16242, 16246, 16251, 16256, 16261, 16267, 16274, 16280, 16288, + 16295, 16304, 16312, 16321, 16330, 16339, 16349, 16359, 16369, 16379, 16389, 16399, 16409, 16419, + 16429, 16439, 16447, 16456, 16465, 16473, 16481, 16489, 16495, 16502, 16508, 16513, 16519, 16523, + 16527, 16531, 16534, 16536, 16539, 16541, 16543, 16544, 16545, 16546, 16547, 16547, 16548, 16549, + 16549, 16549, 16550, 16551, 16551, 16552, 16554, 16554, 16556, 16558, 16559, 16561, 16563, 16565, + 16567, 16570, 16572, 16575, 16578, 16580, 16582, 16584, 16586, 16588, 16590, 16591, 16592, 16593, + 16593, 16593, 16593, 16591, 16589, 16587, 16584, 16580, 16575, 16570, 16564, 16557, 16549, 16540, + 16530, 16519, 16506, 16493, 16478, 16461, 16443, 16423, 16402, 16379, 16354, 16327, 16297, 16266, + 16232, 16195, 16147, 16096, 16039, 15977, 15907, 15828, 15740, 15642, 15531, 15409, 15273, 15122, + 14956, 14775, 14577, 14362, 14130, 13879, 13611, 13325, 13021, 12700, 12361, 12006, 11636, 11250, + 10851, 10440, 10016, 9583, 9142, 8698, 8255, 7815, 7377, 6944, 6515, 6092, 5675, 5266, + 4865, 4475, 4094, 3726, 3370, 3029, 2703, 2393, 2101, 1826, 1571, 1334, 1117, 921, + 744, 588, 451, 335, 235, 128, 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, 0, 0}; +#else +#define PhECU_preTdaFx16ms_sWB_Q14 NULL +#endif +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_SWB_Q14[512] = { + -22482, -22492, -22345, -22020, -21560, -20952, -20236, -19434, -18551, -17624, -16665, -15691, -14716, -13753, + -12810, -11889, -11002, -10152, -9335, -8553, -7813, -7108, -6442, -5806, -5206, -4634, -4091, -3574, + -3084, -2618, -2173, -1748, -1341, -952, -578, -219, 128, 462, 786, 1099, 1405, 1701, + 1989, 2271, 2548, 2818, 3084, 3345, 3601, 3856, 4106, 4354, 4598, 4840, 5082, 5322, + 5559, 5795, 6029, 6263, 6496, 6729, 6961, 7192, 7422, 7652, 7882, 8111, 8339, 8567, + 8795, 9022, 9249, 9475, 9701, 9926, 10151, 10374, 10597, 10819, 11041, 11261, 11481, 11699, + 11917, 12133, 12349, 12563, 12776, 12988, 13198, 13408, 13616, 13823, 14028, 14233, 14437, 14635, + 14826, 15007, 15181, 15344, 15499, 15645, 15782, 15910, 16029, 16139, 16239, 16332, 16415, 16490, + 16557, 16615, 16667, 16710, 16747, 16777, 16800, 16818, 16829, 16835, 16837, 16834, 16827, 16816, + 16803, 16786, 16767, 16746, 16724, 16700, 16675, 16649, 16624, 16601, 16580, 16551, 16524, 16499, + 16475, 16453, 16431, 16411, 16392, 16374, 16358, 16342, 16328, 16313, 16301, 16289, 16278, 16268, + 16258, 16249, 16241, 16234, 16226, 16220, 16214, 16208, 16204, 16200, 16196, 16192, 16188, 16186, + 16184, 16182, 16181, 16179, 16178, 16178, 16177, 16177, 16177, 16178, 16179, 16180, 16181, 16181, + 16183, 16185, 16186, 16188, 16189, 16191, 16192, 16195, 16196, 16198, 16200, 16202, 16204, 16205, + 16207, 16208, 16210, 16211, 16212, 16213, 16215, 16215, 16216, 16217, 16218, 16219, 16219, 16219, + 16220, 16220, 16221, 16221, 16222, 16222, 16222, 16222, 16223, 16223, 16224, 16225, 16226, 16227, + 16228, 16230, 16231, 16233, 16235, 16238, 16240, 16243, 16245, 16249, 16253, 16256, 16260, 16264, + 16269, 16275, 16279, 16285, 16290, 16296, 16302, 16309, 16315, 16322, 16329, 16336, 16343, 16351, + 16358, 16365, 16373, 16381, 16388, 16396, 16403, 16411, 16418, 16425, 16432, 16439, 16446, 16453, + 16460, 16466, 16472, 16478, 16484, 16489, 16494, 16499, 16504, 16509, 16513, 16517, 16520, 16524, + 16527, 16529, 16532, 16534, 16536, 16538, 16540, 16541, 16543, 16543, 16544, 16545, 16546, 16547, + 16547, 16547, 16548, 16548, 16549, 16549, 16550, 16550, 16551, 16551, 16551, 16552, 16553, 16554, + 16555, 16555, 16557, 16558, 16559, 16560, 16562, 16563, 16565, 16566, 16569, 16570, 16572, 16573, + 16576, 16577, 16579, 16581, 16583, 16585, 16586, 16588, 16589, 16590, 16591, 16592, 16592, 16593, + 16593, 16593, 16592, 16592, 16591, 16590, 16589, 16586, 16585, 16581, 16578, 16575, 16571, 16566, + 16562, 16556, 16550, 16543, 16536, 16528, 16520, 16511, 16502, 16490, 16479, 16468, 16455, 16441, + 16426, 16411, 16394, 16376, 16357, 16337, 16316, 16294, 16270, 16245, 16219, 16191, 16154, 16115, + 16075, 16032, 15985, 15934, 15879, 15818, 15751, 15679, 15601, 15517, 15425, 15325, 15218, 15102, + 14978, 14845, 14703, 14551, 14390, 14219, 14038, 13847, 13645, 13434, 13213, 12982, 12741, 12490, + 12230, 11961, 11683, 11396, 11102, 10800, 10492, 10176, 9855, 9529, 9197, 8864, 8532, 8201, + 7872, 7544, 7218, 6894, 6573, 6255, 5940, 5629, 5322, 5020, 4723, 4432, 4147, 3868, + 3596, 3332, 3076, 2828, 2590, 2361, 2141, 1931, 1732, 1543, 1366, 1200, 1044, 901, + 768, 647, 536, 438, 349, 271, 201, 108, 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, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; +#else +#define PhECU_preTdaFx16ms_SWB_Q14 NULL +#endif +#ifdef SUBSET_FB +RAM_ALIGN const Word16 PhECU_preTdaFx16ms_FB_Q14[768] = { + -22463, -22493, -22449, -22334, -22148, -21885, -21560, -21179, -20737, -20250, -19726, -19171, -18581, -17972, + -17340, -16701, -16050, -15401, -14757, -14114, -13474, -12848, -12237, -11637, -11048, -10478, -9922, -9386, + -8864, -8357, -7865, -7393, -6936, -6493, -6069, -5654, -5258, -4874, -4503, -4144, -3801, -3465, + -3140, -2829, -2524, -2230, -1944, -1667, -1399, -1136, -884, -636, -395, -158, 72, 296, + 514, 728, 938, 1144, 1346, 1545, 1739, 1931, 2119, 2305, 2489, 2670, 2849, 3025, + 3199, 3373, 3543, 3713, 3879, 4046, 4211, 4376, 4539, 4700, 4862, 5022, 5182, 5341, + 5499, 5657, 5814, 5970, 6126, 6282, 6437, 6592, 6746, 6901, 7056, 7209, 7362, 7517, + 7669, 7823, 7976, 8129, 8281, 8433, 8585, 8738, 8890, 9040, 9193, 9343, 9495, 9645, + 9796, 9946, 10096, 10245, 10395, 10543, 10693, 10841, 10989, 11137, 11284, 11431, 11578, 11723, + 11869, 12014, 12159, 12303, 12446, 12589, 12733, 12874, 13016, 13157, 13298, 13438, 13577, 13716, + 13855, 13992, 14129, 14266, 14403, 14537, 14667, 14795, 14918, 15037, 15152, 15263, 15371, 15474, + 15573, 15669, 15760, 15847, 15931, 16010, 16084, 16156, 16223, 16287, 16346, 16402, 16453, 16502, + 16546, 16587, 16625, 16659, 16690, 16717, 16742, 16763, 16781, 16797, 16810, 16819, 16827, 16833, + 16836, 16837, 16836, 16833, 16828, 16822, 16815, 16805, 16794, 16783, 16770, 16756, 16743, 16727, + 16712, 16695, 16679, 16663, 16645, 16629, 16612, 16598, 16584, 16565, 16546, 16529, 16511, 16495, + 16479, 16463, 16449, 16434, 16420, 16408, 16395, 16383, 16371, 16360, 16350, 16339, 16329, 16321, + 16311, 16303, 16295, 16287, 16280, 16272, 16266, 16260, 16253, 16247, 16242, 16237, 16232, 16227, + 16223, 16219, 16215, 16211, 16207, 16205, 16202, 16199, 16196, 16194, 16191, 16189, 16187, 16186, + 16184, 16183, 16181, 16180, 16180, 16179, 16178, 16178, 16177, 16177, 16177, 16177, 16177, 16177, + 16178, 16178, 16179, 16179, 16180, 16181, 16182, 16183, 16184, 16185, 16186, 16187, 16188, 16189, + 16190, 16191, 16193, 16194, 16195, 16196, 16197, 16199, 16200, 16201, 16202, 16203, 16205, 16206, + 16206, 16207, 16208, 16209, 16210, 16211, 16212, 16212, 16213, 16214, 16215, 16215, 16216, 16216, + 16217, 16218, 16218, 16218, 16219, 16219, 16219, 16220, 16220, 16220, 16221, 16221, 16221, 16221, + 16221, 16222, 16222, 16222, 16223, 16223, 16223, 16224, 16224, 16225, 16225, 16226, 16227, 16227, + 16228, 16229, 16230, 16231, 16233, 16234, 16235, 16237, 16237, 16239, 16241, 16243, 16245, 16247, + 16249, 16252, 16254, 16257, 16260, 16263, 16266, 16268, 16271, 16275, 16278, 16282, 16286, 16290, + 16294, 16298, 16301, 16305, 16310, 16314, 16319, 16323, 16328, 16332, 16337, 16342, 16347, 16352, + 16357, 16361, 16366, 16371, 16377, 16382, 16387, 16391, 16396, 16402, 16407, 16412, 16417, 16421, + 16426, 16431, 16436, 16441, 16445, 16450, 16454, 16458, 16463, 16467, 16471, 16475, 16480, 16482, + 16486, 16490, 16494, 16497, 16500, 16504, 16507, 16510, 16511, 16514, 16517, 16519, 16522, 16524, + 16526, 16528, 16530, 16532, 16533, 16535, 16536, 16538, 16539, 16540, 16541, 16542, 16542, 16543, + 16543, 16544, 16545, 16545, 16546, 16546, 16546, 16547, 16547, 16547, 16548, 16548, 16548, 16548, + 16549, 16549, 16549, 16549, 16550, 16550, 16550, 16551, 16551, 16551, 16552, 16552, 16553, 16554, + 16554, 16555, 16556, 16556, 16557, 16558, 16559, 16560, 16561, 16562, 16563, 16564, 16565, 16566, + 16567, 16568, 16570, 16571, 16572, 16572, 16574, 16575, 16576, 16577, 16579, 16580, 16581, 16582, + 16583, 16585, 16586, 16587, 16588, 16589, 16589, 16590, 16591, 16592, 16592, 16593, 16593, 16593, + 16593, 16593, 16593, 16593, 16593, 16592, 16592, 16591, 16590, 16589, 16588, 16586, 16585, 16583, + 16581, 16579, 16576, 16574, 16572, 16569, 16566, 16562, 16559, 16555, 16551, 16546, 16542, 16538, + 16533, 16527, 16521, 16515, 16510, 16503, 16496, 16489, 16481, 16474, 16465, 16457, 16448, 16439, + 16428, 16419, 16408, 16396, 16385, 16373, 16360, 16347, 16333, 16320, 16305, 16290, 16274, 16258, + 16240, 16223, 16205, 16186, 16160, 16134, 16109, 16082, 16054, 16024, 15993, 15961, 15926, 15888, + 15849, 15808, 15763, 15717, 15667, 15615, 15560, 15502, 15441, 15376, 15308, 15236, 15161, 15082, + 14999, 14913, 14822, 14727, 14628, 14525, 14417, 14306, 14190, 14069, 13944, 13814, 13679, 13541, + 13398, 13250, 13098, 12943, 12782, 12616, 12447, 12273, 12096, 11915, 11729, 11541, 11348, 11151, + 10952, 10749, 10543, 10335, 10123, 9909, 9692, 9473, 9253, 9032, 8810, 8589, 8369, 8149, + 7929, 7711, 7492, 7276, 7059, 6845, 6631, 6418, 6207, 5997, 5789, 5582, 5378, 5175, + 4975, 4777, 4583, 4389, 4200, 4012, 3827, 3646, 3468, 3294, 3123, 2956, 2793, 2634, + 2479, 2328, 2181, 2039, 1902, 1768, 1639, 1517, 1398, 1284, 1176, 1072, 973, 879, + 791, 707, 629, 556, 486, 423, 364, 310, 261, 213, 163, 85, 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, 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, 0, 0, 0, 0}; +#else +#define PhECU_preTdaFx16ms_FB_Q14 NULL +#endif + +RAM_ALIGN const Word16 *const PhECU_wins[5][3] = { + /* 3ms hamm(left part) , 16ms(center IWHR(periodic)*MDCT-anaQ14) , 2ms(initial MDCT-ana in Q14) */ + /*8 kHz*/ {PhECU_whr16ms_NB_Q15, PhECU_preTdaFx16ms_NB_Q14, PhECU_preTdaFx16ms_128_pre_Q14}, + /*16 kHz*/ {PhECU_whr16ms_WB_Q15, PhECU_preTdaFx16ms_WB_Q14, PhECU_preTdaFx16ms_256_pre_Q14}, + /*24 kHz*/ {PhECU_whr16ms_sWB_Q15, PhECU_preTdaFx16ms_sWB_Q14, PhECU_preTdaFx16ms_384_pre_Q14}, + /*32 kHz*/ {PhECU_whr16ms_SWB_Q15, PhECU_preTdaFx16ms_SWB_Q14, PhECU_preTdaFx16ms_512_pre_Q14}, + /*48 kHz*/ {PhECU_whr16ms_FB_Q15, PhECU_preTdaFx16ms_FB_Q14, PhECU_preTdaFx16ms_768_pre_Q14}}; + +/* x=(0:(5*8-1))*(2*pi)/32; y=sin(x);y_int=max(-32768,min(32767,round(y*32768))), y_int/32768 */ +/* 1.25 *2*pi table for low complex and low angle resolution rand_phase_fx */ +RAM_ALIGN const Word16 sincos_lowres_tab_sinQ15_fx[40] = { + 0, 6393, 12540, 18205, 23170, 27246, 30274, 32138, 32767, 32138, 30274, 27246, 23170, 18205, + 12540, 6393, 0, -6393, -12540, -18205, -23170, -27246, -30274, -32138, -32768, -32138, -30274, -27246, + -23170, -18205, -12540, -6393, 0, 6393, 12540, 18205, 23170, 27246, 30274, 32138}; + +/* (PHECU_LA_48K == 0) */ + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 w_new_fs_8_LA_0[OLA_LEN_8K] = {0, 411, 1623, 3574, 6169, 9275, 12738, + 16384, 20030, 23493, 26599, 29194, 31145, 32357}; + + +RAM_ALIGN const Word16 w_old_fs_8_LA_0[OLA_LEN_8K] = { + + /* ( 32768-fliplr(w_new_fs_8_LA_0) ) *[whr3ms(0:13)*/ + 2621, 2721, 3001, 3401, 3836, 4205, 4411, 4377, 4063, 3475, 2673, 1766, 901, 253}; +#else +#define w_new_fs_8_LA_0 NULL +#define w_old_fs_8_LA_0 NULL +#endif /* SUBSET_NB */ + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 w_new_fs_16_LA_0[OLA_LEN_16K] = { + 0, 103, 411, 919, 1623, 2511, 3574, 4799, 6169, 7667, 9275, 10973, 12738, 14550, + 16384, 18218, 20030, 21795, 23493, 25101, 26599, 27969, 29194, 30257, 31145, 31849, 32357, 32665}; + +RAM_ALIGN const Word16 w_old_fs_16_LA_0[OLA_LEN_16K] = {2621, 2646, 2719, 2835, 2990, 3175, 3379, 3592, 3801, 3994, + 4158, 4282, 4355, 4369, 4317, 4196, 4005, 3746, 3425, 3050, + 2635, 2192, 1740, 1299, 889, 531, 250, 66}; +#else +#define w_new_fs_16_LA_0 NULL +#define w_old_fs_16_LA_0 NULL +#endif /* SUBSET_WB */ + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 w_new_fs_24_LA_0[OLA_LEN_24K] = { + 0, 46, 183, 411, 728, 1133, 1623, 2195, 2847, 3574, 4374, 5240, 6169, 7155, + 8192, 9275, 10398, 11555, 12738, 13942, 15160, 16384, 17608, 18826, 20030, 21213, 22370, 23493, + 24576, 25613, 26599, 27528, 28394, 29194, 29921, 30573, 31145, 31635, 32040, 32357, 32585, 32722}; + +RAM_ALIGN const Word16 w_old_fs_24_LA_0[OLA_LEN_24K] = { + 2621, 2632, 2665, 2718, 2790, 2881, 2987, 3106, 3235, 3372, 3512, 3653, 3790, 3919, + 4038, 4143, 4229, 4295, 4337, 4353, 4340, 4298, 4225, 4121, 3986, 3821, 3628, 3408, + 3165, 2902, 2622, 2330, 2032, 1732, 1437, 1152, 884, 640, 426, 249, 114, 30}; +#else +#define w_new_fs_24_LA_0 NULL +#define w_old_fs_24_LA_0 NULL +#endif /* SUBSET_SSWB */ + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 w_new_fs_32_LA_0[OLA_LEN_32K] = { + 0, 26, 103, 231, 411, 640, 919, 1247, 1623, 2044, 2511, 3022, 3574, 4167, + 4799, 5467, 6169, 6903, 7667, 8459, 9275, 10114, 10973, 11848, 12738, 13640, 14550, 15465, + 16384, 17303, 18218, 19128, 20030, 20920, 21795, 22654, 23493, 24309, 25101, 25865, 26599, 27301, + 27969, 28601, 29194, 29746, 30257, 30724, 31145, 31521, 31849, 32128, 32357, 32537, 32665, 32742}; + +RAM_ALIGN const Word16 w_old_fs_32_LA_0[OLA_LEN_32K] = { + 2621, 2628, 2646, 2676, 2717, 2770, 2832, 2904, 2985, 3073, 3167, 3266, 3368, 3473, 3578, 3682, 3784, 3882, 3974, + 4059, 4135, 4202, 4257, 4299, 4328, 4342, 4340, 4323, 4288, 4236, 4167, 4081, 3977, 3856, 3719, 3567, 3400, 3220, + 3028, 2826, 2615, 2398, 2176, 1952, 1728, 1506, 1290, 1081, 882, 697, 528, 377, 248, 143, 65, 17}; +#else +#define w_new_fs_32_LA_0 NULL +#define w_old_fs_32_LA_0 NULL +#endif /* SUBSET_SWB */ + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 w_new_fs_48_LA_0[OLA_LEN_48K] = { + 0, 11, 46, 103, 183, 286, 411, 558, 728, 919, 1133, 1367, 1623, 1899, + 2195, 2511, 2847, 3201, 3574, 3965, 4374, 4799, 5240, 5697, 6169, 6655, 7155, 7667, + 8192, 8728, 9275, 9832, 10398, 10973, 11555, 12144, 12738, 13338, 13942, 14550, 15160, 15771, + 16384, 16997, 17608, 18218, 18826, 19430, 20030, 20624, 21213, 21795, 22370, 22936, 23493, 24040, + 24576, 25101, 25613, 26113, 26599, 27071, 27528, 27969, 28394, 28803, 29194, 29567, 29921, 30257, + 30573, 30869, 31145, 31401, 31635, 31849, 32040, 32210, 32357, 32482, 32585, 32665, 32722, 32757}; + +RAM_ALIGN const Word16 w_old_fs_48_LA_0[OLA_LEN_48K] = { + 2621, 2624, 2632, 2646, 2664, 2688, 2717, 2750, 2789, 2831, 2878, 2929, 2983, 3041, 3101, 3164, 3229, + 3296, 3365, 3434, 3504, 3573, 3643, 3711, 3778, 3844, 3907, 3967, 4024, 4078, 4128, 4173, 4213, 4248, + 4278, 4301, 4319, 4330, 4334, 4331, 4321, 4303, 4278, 4246, 4206, 4158, 4102, 4038, 3967, 3889, 3803, + 3710, 3611, 3505, 3392, 3274, 3150, 3021, 2888, 2750, 2609, 2465, 2319, 2171, 2022, 1873, 1724, 1576, + 1430, 1287, 1147, 1011, 880, 755, 637, 527, 424, 331, 248, 175, 114, 65, 29, 7}; +#else +#define w_new_fs_48_LA_0 NULL +#define w_old_fs_48_LA_0 NULL +#endif /* SUBSET_FB */ + +RAM_ALIGN const Word16 *const w_new[5] = {w_new_fs_8_LA_0, w_new_fs_16_LA_0, w_new_fs_24_LA_0, w_new_fs_32_LA_0, + w_new_fs_48_LA_0}; +RAM_ALIGN const Word16 *const w_old[5] = {w_old_fs_8_LA_0, w_old_fs_16_LA_0, w_old_fs_24_LA_0, w_old_fs_32_LA_0, + w_old_fs_48_LA_0}; + +RAM_ALIGN const Word16 COPY_LEN[5] = {COPY_LEN_8K, COPY_LEN_16K, COPY_LEN_24K, COPY_LEN_32K, COPY_LEN_48K}; /* 2ms */ +RAM_ALIGN const Word16 OLA_LEN[5] = {OLA_LEN_8K, OLA_LEN_16K, OLA_LEN_24K, OLA_LEN_32K, OLA_LEN_48K}; /*1.75 ms mix */ + +RAM_ALIGN const Word16 num_FsByResQ0[5] = {LPROT8K, LPROT16K, LPROT24K, LPROT32K, LPROT48K}; +RAM_ALIGN const Word16 *const LprotSzPtr = num_FsByResQ0; +RAM_ALIGN const Word16 InvLprot_Q22[5] = {INV_LPROT8K_Q22, INV_LPROT16K_Q22, INV_LPROT24K_Q22, INV_LPROT32K_Q22, + INV_LPROT48K_Q22}; +RAM_ALIGN const Word16 PhEcuFftScale[5] = {0, 0, 8, 0, 4}; + +RAM_ALIGN const Word16 oneOverFrameQ15Tab[5] = {INV_L_FRAME8K_Q15, INV_L_FRAME16K_Q15, INV_L_FRAME24K_Q15, + INV_L_FRAME32K_Q15, INV_L_FRAME48K_Q15}; + + +RAM_ALIGN const Word16 PhEcu_Xsav_Flt2FxDnShift[5] = {6, 7, 7, 8, 8}; /* TOTAL FFT adjutmenst shift */ +RAM_ALIGN const Word16 PhEcu_Xsav_Flt2FxScaleQ15[5] = {32767, 32767, 21845, 32767, + 21845}; /* fractional fft adjustment 1./ fft_fs_scale */ + +RAM_ALIGN const Word16 PhEcu_frac_thr_rise_lin_Q15[MAX_LGW] = {3277, 3277, 3277, 3277, 3277, + 3277, 3277, 3277, 3277}; /* for now all fixed to 10dB */ +RAM_ALIGN const Word16 PhEcu_frac_thr_decay_lin_Q15[MAX_LGW] = { + 3277, 3277, 3277, 3277, 3277, + 3277, 3277, 3277, 3277}; /* thresh_rise_dB=10; thresh_lin = 1.0/( 10^(thresh_rise_dB/10) ); */ + +RAM_ALIGN const Word16 mdct_grp_bins_fx[MAX_LGW + 2] = {4, 14, 24, 44, 84, 164, 244, 324, 404, 484}; +RAM_ALIGN const Word16 xavg_N_grp_fx[5] = {4, 5, 6, 7, 8}; + + +RAM_ALIGN const Word16 spec_shape_headroom[5] = {3, 4, 4, 4, 4}; +RAM_ALIGN const Word16 rectLengthTab[NUM_SAMP_FREQ] = {80, 160, 240, 320, 480, 960}; /* 10ms */ +RAM_ALIGN const Word16 hamm_len2Tab[5] = {24, 48, 72, 96, 144}; /* 3 ms*/ + +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR +RAM_ALIGN const Word16 PLC_FADEOUT_TYPE_2_SELECTOR = 10; /* can take values from 0 to 10, default is 10 for longer fadeout*/ +#else +# ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH +RAM_ALIGN const Word16 FADE_OUT_TYPE_2_ALPHA_5MS[30] = { /* 0.5^(nbLostFramesInRow + LC3_ROUND(100.0/frame_dms) - 1) * frame_dms/100.0)*/ + 16384,11585,8192,5792,4096,2896,2048,1448,1024,724,512,362,256,181,128,91,64,45,32,23,16,11,8,6,4,3,2,1,1,1}; +RAM_ALIGN const Word16 FADE_OUT_TYPE_2_ALPHA_2_5MS[60] = { /* 0.5^(nbLostFramesInRow + LC3_ROUND(100.0/frame_dms) - 1) * frame_dms/100.0)*/ + 16384,13777,11585,9742,8192,6889,5793,4871,4096,3444,2896,2435,2048,1722,1448,1218,1024,861,724,609,512,431,362,304,256,215,181,152,128,108,91,76,64,54,45,38,32,27,23,19,16,13,11,10,8,7,6,5,4,3,3,2,2,2,1,1,1,1,1,1}; +# endif +#endif + +RAM_ALIGN const Word16 NN_thresh = 0x7800; /* 30*2^10 */ +RAM_ALIGN const Word16 NN_thresh_exp = -10; +/* Tone detector */ +#ifdef CR8_E_TONE_DETECTOR +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 TD_HR_thresh_10ms = 83402; +# ifdef ENABLE_075_DMS_MODE +RAM_ALIGN const Word32 TD_HR_thresh_7_5ms = 743496; +# endif +RAM_ALIGN const Word32 TD_HR_thresh_5ms = 382564; +RAM_ALIGN const Word32 TD_HR_thresh_2_5ms = 301695; +# endif /* ENABLE_HR_MODE */ +#endif /* CR8_E_TONE_DETECTOR */ +RAM_ALIGN const Word32 BW_thresh_quiet[4] = {0x14000000, 0xA000000, 0xA000000, 0xA000000}; /* [20,10,10,10]*2^24 */ +RAM_ALIGN const Word16 BW_thresh_quiet_exp = 31 - 24; +RAM_ALIGN const Word16 BW_thresh_brickwall[4] = { + 1036, 164, 327, 327}; /* (1/(10^(ctrl.BW_thresh_brickwall/10))*2^15) with [15,23,20,20] dB*/ + +RAM_ALIGN const Word16 BW_brickwall_dist[4] = {4, 4, 3, 1}; +RAM_ALIGN const Word16 BW_warp_idx_start_16k[4] = { + 53, 0, 0, 0}; /* indices for warped bands, with an offset of [17,23,23,23] bins for the start_idx */ +RAM_ALIGN const Word16 BW_warp_idx_stop_16k[4] = { + 63, 0, 0, + 0}; /*'-1' since this is not matlab and another '-1' because of the different formatting of acc_coeff_per_band*/ +RAM_ALIGN const Word16 BW_warp_idx_start_24k[4] = {47, 59, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_24k[4] = {56, 63, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_32k[4] = {44, 54, 60, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_32k[4] = {52, 59, 63, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_48k[4] = {41, 51, 57, 61}; +RAM_ALIGN const Word16 BW_warp_idx_stop_48k[4] = {49, 55, 60, 63}; +RAM_ALIGN const Word16 *const BW_warp_idx_start_all[MAX_BW_BANDS_NUMBER - 1] = { + BW_warp_idx_start_16k, BW_warp_idx_start_24k, BW_warp_idx_start_32k, BW_warp_idx_start_48k}; +RAM_ALIGN const Word16 *const BW_warp_idx_stop_all[MAX_BW_BANDS_NUMBER - 1] = { + BW_warp_idx_stop_16k, BW_warp_idx_stop_24k, BW_warp_idx_stop_32k, BW_warp_idx_stop_48k}; + +RAM_ALIGN const Word16 BW_brickwall_dist_5ms[4] = {4, 4, 3, 1}; +RAM_ALIGN const Word16 BW_warp_idx_start_16k_5ms[4] = {39, 0, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_16k_5ms[4] = {49, 0, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_24k_5ms[4] = {35, 47, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_24k_5ms[4] = {44, 51, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_32k_5ms[4] = {34, 44, 50, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_32k_5ms[4] = {42, 49, 53, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_48k_5ms[4] = {32, 42, 48, 52}; +RAM_ALIGN const Word16 BW_warp_idx_stop_48k_5ms[4] = {40, 46, 51, 54}; +RAM_ALIGN const Word16 *const BW_warp_idx_start_all_5ms[MAX_BW_BANDS_NUMBER - 1] = { + BW_warp_idx_start_16k_5ms, BW_warp_idx_start_24k_5ms, BW_warp_idx_start_32k_5ms, BW_warp_idx_start_48k_5ms}; +RAM_ALIGN const Word16 *const BW_warp_idx_stop_all_5ms[MAX_BW_BANDS_NUMBER - 1] = { + BW_warp_idx_stop_16k_5ms, BW_warp_idx_stop_24k_5ms, BW_warp_idx_stop_32k_5ms, BW_warp_idx_stop_48k_5ms}; + +RAM_ALIGN const Word16 BW_brickwall_dist_2_5ms[4] = {4, 4, 3, 1}; +RAM_ALIGN const Word16 BW_warp_idx_start_16k_2_5ms[4] = {24, 0, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_16k_2_5ms[4] = {34, 0, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_24k_2_5ms[4] = {24, 35, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_24k_2_5ms[4] = {32, 39, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_32k_2_5ms[4] = {24, 33, 39, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_32k_2_5ms[4] = {31, 38, 42, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_48k_2_5ms[4] = {22, 31, 37, 41}; +RAM_ALIGN const Word16 BW_warp_idx_stop_48k_2_5ms[4] = {29, 35, 40, 43}; +RAM_ALIGN const Word16 *const BW_warp_idx_start_all_2_5ms[MAX_BW_BANDS_NUMBER - 1] = { + BW_warp_idx_start_16k_2_5ms, BW_warp_idx_start_24k_2_5ms, BW_warp_idx_start_32k_2_5ms, BW_warp_idx_start_48k_2_5ms}; +RAM_ALIGN const Word16 *const BW_warp_idx_stop_all_2_5ms[MAX_BW_BANDS_NUMBER - 1] = { + BW_warp_idx_stop_16k_2_5ms, BW_warp_idx_stop_24k_2_5ms, BW_warp_idx_stop_32k_2_5ms, BW_warp_idx_stop_48k_2_5ms}; + +# ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 BW_brickwall_dist_7_5ms[4] = {4, 4, 3, 2}; +RAM_ALIGN const Word16 BW_warp_idx_start_16k_7_5ms[4] = {51, 0, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_16k_7_5ms[4] = {63, 0, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_24k_7_5ms[4] = {45, 58, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_24k_7_5ms[4] = {55, 63, 0, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_32k_7_5ms[4] = {42, 53, 60, 0}; +RAM_ALIGN const Word16 BW_warp_idx_stop_32k_7_5ms[4] = {51, 58, 63, 0}; +RAM_ALIGN const Word16 BW_warp_idx_start_48k_7_5ms[4] = {40, 51, 57, 61}; +RAM_ALIGN const Word16 BW_warp_idx_stop_48k_7_5ms[4] = {48, 55, 60, 63}; +RAM_ALIGN const Word16 *const BW_warp_idx_start_all_7_5ms[] = { + BW_warp_idx_start_16k_7_5ms, BW_warp_idx_start_24k_7_5ms, BW_warp_idx_start_32k_7_5ms, BW_warp_idx_start_48k_7_5ms}; +RAM_ALIGN const Word16 *const BW_warp_idx_stop_all_7_5ms[] = { + BW_warp_idx_stop_16k_7_5ms, BW_warp_idx_stop_24k_7_5ms, BW_warp_idx_stop_32k_7_5ms, BW_warp_idx_stop_48k_7_5ms}; +# endif + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 BW_cutoff_bin_all[] = {80, 160, 240, 320, 400, 400}; +RAM_ALIGN const Word16 BW_cutoff_bin_all_HR[] = {80, 160, 240, 320, 400, 400}; +RAM_ALIGN const Word16 BW_cutoff_bits_all[] = {0, 1, 2, 2, 3, 0}; +#else /* ENABLE_HR_MODE */ +RAM_ALIGN const Word16 BW_cutoff_bin_all[] = {80, 160, 240, 320, 400}; +RAM_ALIGN const Word16 BW_cutoff_bits_all[] = {0, 1, 2, 2, 3}; +#endif /* ENABLE_HR_MODE */ + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 LowDelayShapes_n960_len[6] = {130, 260, 390, 520, 780, 1560}; +#else +RAM_ALIGN const Word16 LowDelayShapes_n960_len[5] = {130, 260, 390, 520, 780}; +#endif +RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes[NUM_SAMP_FREQ] = {30, + 60, + 90, + 120, + 180 +#ifdef ENABLE_HR_MODE + , 360 +#endif +}; + +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_HR_MODE +const Word16 LowDelayShapes_n960_len_7_5ms[6] = {106, 212, 318, 424, 636, 1272}; +# else +const Word16 LowDelayShapes_n960_len_7_5ms[5] = {106, 212, 318, 424, 636}; +# endif +const Word16 LowDelayShapes_n960_la_zeroes_7_5ms[NUM_SAMP_FREQ] = {14, 28, 42, 56, 84 +# ifdef ENABLE_HR_MODE + , 168 +# endif +}; +# ifdef ENABLE_HR_MODE +# ifdef SUBSET_NB +const Word32 MDCT_WINDOW_FS_8000_frame_ms_75[106] = { + 4627440, 11253200, 21594770, 36220454, 55523513, 79715027, 108949241, 143324500, 182870991, + 227518888, 277136190, 331449220, 390143896, 452770029, 518831181, 587821768, 659169189, 732247130, + 806397033, 880930033, 955136210, 1028289061, 1099721013, 1168761191, 1234831373, 1297335398, 1355817068, + 1409866562, 1459158403, 1503372583, 1542341368, 1575958063, 1604141948, 1626962506, 1644516439, 1657006271, + 1664740913, 1668084651, 1667510566, 1663566793, 1656808751, 1647805301, 1637186879, 1625507591, 1613355502, + 1601336341, 1590266842, 1579708994, 1571001708, 1564080946, 1558867236, 1555257286, 1553127519, 1552339115, + 1552734517, 1554146897, 1556401387, 1559318893, 1562715844, 1566405205, -1570197717, -1573904742, -1577333468, + -1580290211, -1582582625, -1584022156, -1584425628, -1583621336, -1581452727, -1577790475, -1572531065, -1565603566, + -1556974029, -1546637213, -1533223967, -1517247857, -1497930249, -1474813741, -1447477329, -1415559391, -1378853853, + -1337198324, -1290524957, -1238912889, -1182546000, -1121735805, -1056935470, -988679598, -917579357, -844370566, + -769774729, -694577976, -619621377, -545775321, -473935196, -404978161, -339758802, -279035319, -223452287, + -173535871, -129697804, -92268521, -61482210, -37424210, -19913685, -8400842}; +# else +# define MDCT_WINDOW_FS_8000_frame_ms_75 NULL +# endif +# ifdef SUBSET_WB +const Word32 MDCT_WINDOW_FS_16000_frame_ms_75[212] = { + 2448850, 4225281, 6560055, 9518849, 13169928, 17558685, 22724572, 28709046, 35532706, + 43206772, 51759643, 61197652, 71531905, 82773688, 94926633, 107995294, 121978042, 136866522, + 152653815, 169326944, 186873869, 205260070, 224464206, 244469708, 265226672, 286694090, 308842566, + 331620399, 354982140, 378884306, 403282899, 428126460, 453358062, 478925896, 504771155, 530831178, + 557056009, 583378298, 609738583, 636071404, 662314239, 688406753, 714278048, 739869110, 765133864, + 789997902, 814413107, 838333634, 861699657, 884456686, 906561215, 927970820, 948653245, 968562870, + 987675635, 1005965699, 1023398499, 1039938064, 1055570884, 1070287165, 1084066983, 1096897234, 1108786027, + 1119713468, 1129673618, 1138691939, 1146759882, 1153881756, 1160087929, 1165385723, 1169796304, 1173355296, + 1176085471, 1178017803, 1179194996, 1179657892, 1179448026, 1178622117, 1177223060, 1175290297, 1172896803, + 1170081494, 1166887472, 1163391971, 1159633509, 1155652038, 1151518603, 1147273273, 1142969676, 1138666561, + 1134412515, 1130255869, 1126558117, 1122496331, 1118765157, 1115363902, 1112285558, 1109526458, 1107080797, + 1104939816, 1103098430, 1101543766, 1100269289, 1099261964, 1098510648, 1098002762, 1097726182, 1097665183, + 1097807233, 1098135900, 1098637579, 1099295163, 1100094642, 1101018650, 1102052611, 1103178569, 1104381936, + 1105644852, 1106951761, 1108284322, -1109627660, -1110963442, -1112276637, -1113548581, -1114763260, -1115902204, + -1116950143, -1117888308, -1118701309, -1119370903, -1119882282, -1120217558, -1120362527, -1120300271, -1120018073, + -1119500244, -1118735095, -1117710865, -1116417682, -1114844247, -1112986355, -1110833953, -1108385410, -1105635984, + -1102584489, -1099232427, -1095578582, -1091628491, -1086655755, -1081531176, -1075887278, -1069676603, -1062851542, + -1055375495, -1047209387, -1038304906, -1028645771, -1018191542, -1006905821, -994788854, -981815515, -967960849, + -953236015, -937625018, -921120793, -903739802, -885489416, -866385515, -846456825, -825718325, -804213946, + -781984241, -759069751, -735509614, -711369811, -686704607, -661557703, -636008311, -610118476, -583941228, + -557562076, -531035554, -504439473, -477846967, -451338312, -424989596, -398869327, -373061710, -347653667, + -322717851, -298330826, -274560095, -251498346, -229196510, -207718889, -187124805, -167466055, -148790641, + -131139192, -114544857, -99042767, -84660988, -71425324, -59356162, -48470733, -38776535, -30272788, + -22943830, -16759108, -11669404, -7602417, -4461896 }; +# else +# define MDCT_WINDOW_FS_16000_frame_ms_75 NULL +# endif +# ifdef SUBSET_SSWB +const Word32 MDCT_WINDOW_FS_24000_frame_ms_75[318] = { + 3569045, 5343308, 7469087, 10008734, 12994076, 16456850, 20430606, 24935492, 29988837, + 35611849, 41823777, 48643571, 56071893, 64113030, 72783590, 82094564, 92046985, 102645585, + 113894977, 125803748, 138373328, 151602749, 165496877, 180058414, 195279760, 211161232, 227698398, + 244884561, 262716182, 281188032, 300290267, 320009308, 340323456, 361229416, 382724592, 404784463, + 427382077, 450499367, 474123138, 498236134, 522813796, 547827872, 573261791, 599094644, 625301687, + 651864990, 678758112, 705953149, 733423301, 761143017, 789088191, 817226769, 845526155, 873965021, + 902516713, 931147088, 959825021, 988524208, 1017210384, 1045855673, 1074425690, 1102896296, 1131233244, + 1159399102, 1187365932, 1215118091, 1242623432, 1269848445, 1296758792, 1323338775, 1349569176, 1375419011, + 1400856664, 1425860452, 1450405500, 1474469418, 1498033883, 1521084216, 1543600669, 1565562699, 1586950362, + 1607758181, 1627973678, 1647578495, 1666558705, 1684890994, 1702569411, 1719588669, 1735945131, 1751628259, + 1766631537, 1780942408, 1794568179, 1807511369, 1819759624, 1831304037, 1842145330, 1852303571, 1861781063, + 1870563512, 1878654482, 1886073254, 1892829269, 1898924017, 1904366694, 1909168622, 1913346034, 1916917451, + 1919887595, 1922277229, 1924098512, 1925377637, 1926138245, 1926390110, 1926159966, 1925475348, 1924365664, + 1922840889, 1920921471, 1918639476, 1916032510, 1913117957, 1909905898, 1906425851, 1902721668, 1898817211, + 1894724624, 1890460570, 1886061947, 1881561147, 1876974490, 1872321669, 1867634952, 1862942467, 1858269659, + 1853636539, 1849063935, 1844532585, 1840901848, 1836281978, 1831977326, 1827914309, 1824090826, 1820508133, + 1817156298, 1814036518, 1811148878, 1808486122, 1806045111, 1803824889, 1801820200, 1800024837, 1798435525, + 1797047955, 1795856425, 1794854508, 1794036436, 1793397182, 1792930395, 1792629275, 1792486811, 1792496288, + 1792650932, 1792943382, 1793366271, 1793912436, 1794574259, 1795343928, 1796214319, 1797177519, 1798225910, + 1799351580, 1800546365, 1801802795, 1803112835, 1804468826, 1805862173, 1807285016, 1808728934, 1810185719, + -1811649011, -1813108149, -1814556719, -1815986412, -1817388652, -1818755380, -1820077746, -1821347804, -1822557195, + -1823698097, -1824761958, -1825740466, -1826625594, -1827409009, -1828083190, -1828639928, -1829071236, -1829369628, + -1829527454, -1829537126, -1829391729, -1829084485, -1828608410, -1827956837, -1827123677, -1826104316, -1824893520, + -1823485537, -1821875510, -1820060164, -1818037432, -1815802468, -1813351581, -1810685587, -1807803281, -1804699559, + -1801376829, -1797838749, -1794078176, -1790099212, -1785902823, -1781420977, -1775757613, -1770414541, -1764657397, + -1758514553, -1751966917, -1744988832, -1737559493, -1729660865, -1721279216, -1712390301, -1702968220, -1693002531, + -1682487980, -1671402851, -1659722977, -1647435681, -1634547191, -1621051754, -1606928538, -1592163286, -1576765074, + -1560734340, -1544063625, -1526744164, -1508774562, -1490169863, -1470931267, -1451061598, -1430573380, -1409469788, + -1387774154, -1365486503, -1342628496, -1319212449, -1295268938, -1270814307, -1245866917, -1220443956, -1194576202, + -1168294208, -1141628864, -1114589888, -1087212858, -1059529377, -1031588154, -1003401722, -974995147, -946412027, + -917694623, -888859295, -859943075, -830987474, -802029563, -773092402, -744234412, -715477138, -686865195, + -658426713, -630207057, -602244426, -574581369, -547253226, -520293544, -493735699, -467628500, -441995738, + -416889401, -392319671, -368337811, -344954670, -322202233, -300117288, -278711744, -258020476, -238052276, + -218834457, -200381964, -182706579, -165829103, -149762124, -134517743, -120107705, -106542511, -93830987, + -81979923, -70993541, -60872925, -51615362, -43213756, -35655914, -28924065, -22994343, -17836407, + -13413907, -9700456, -6939916 }; +# else +# define MDCT_WINDOW_FS_24000_frame_ms_75 NULL +# endif +# ifdef SUBSET_SWB +const Word32 MDCT_WINDOW_FS_32000_frame_ms_75[424] = { + 2898737, 4022405, 5281441, 6723878, 8372060, 10235970, 12328606, 14657777, 17238266, + 20075996, 23180406, 26552429, 30204258, 34141418, 38374110, 42901881, 47726394, 52848657, + 58275464, 64009892, 70057240, 76417471, 83091786, 90080421, 97386522, 105014921, 112964415, + 121235754, 129827911, 138744722, 147986004, 157551876, 167437738, 177647147, 188174741, 199022831, + 210184946, 221662871, 233452811, 245554560, 257961285, 270671503, 283672733, 296964439, 310542664, + 324409414, 338557330, 352975270, 367652577, 382584217, 397764861, 413190770, 428852496, 444742036, + 460850489, 477166934, 493686689, 510401963, 527305552, 544386461, 561639986, 579055156, 596625027, + 614334635, 632177187, 650141962, 668224093, 686407908, 704684687, 723041108, 741470500, 759961912, + 778506953, 797092489, 815707619, 834339025, 852979862, 871616777, 890238991, 908834402, 927390921, + 945902091, 964354406, 982734524, 1001028580, 1019227984, 1037324578, 1055313224, 1073178103, 1090910419, + 1108493143, 1125919532, 1143183321, 1160279970, 1177195986, 1193922020, 1210443853, 1226757428, 1242848720, + 1258716966, 1274346305, 1289734310, 1304873724, 1319761111, 1334385677, 1348742053, 1362821420, 1376620057, + 1390134975, 1403361262, 1416296924, 1428929625, 1441257929, 1453270092, 1464967234, 1476341997, 1487396355, + 1498127704, 1508535547, 1518610856, 1528355951, 1537762901, 1546836443, 1555575202, 1563981756, 1572051527, + 1579779433, 1587162378, 1594203212, 1600912026, 1607289540, 1613333597, 1619037500, 1624404299, 1629439428, + 1634149881, 1638537653, 1642603536, 1646350593, 1649779860, 1652898979, 1655708955, 1658229426, 1660449352, + 1662377545, 1664024217, 1665388315, 1666481709, 1667311651, 1667891108, 1668216427, 1668300198, 1668150304, + 1667777789, 1667191944, 1666404102, 1665413150, 1664228568, 1662860495, 1661323561, 1659629730, 1657785817, + 1655794977, 1653662566, 1651401295, 1649028654, 1646557403, 1643989827, 1641331208, 1638586818, 1635770553, + 1632894967, 1629971201, 1627004437, 1624002536, 1620971847, 1617927153, 1614878122, 1611835451, 1608805100, + 1605795099, 1602815547, 1599884473, 1596942341, 1594771673, 1591702411, 1588839753, 1586088059, 1583448720, + 1580925703, 1578521775, 1576232766, 1574055288, 1571990953, 1570040827, 1568202332, 1566472498, 1564851004, + 1563337829, 1561931261, 1560628909, 1559429084, 1558330506, 1557331359, 1556429824, 1555624516, 1554913143, + 1554292592, 1553760945, 1553317125, 1552958916, 1552683122, 1552487276, 1552369480, 1552327252, 1552357490, + 1552457675, 1552625785, 1552859126, 1553154340, 1553508826, 1553920495, 1554386414, 1554903212, 1555468295, + 1556079427, 1556733719, 1557427851, 1558158741, 1558924090, 1559721218, 1560546581, 1561397206, 1562271110, + 1563165114, 1564075458, 1564999378, 1565934440, 1566877694, 1567825218, -1568775555, -1569724227, -1570669763, + -1571608214, -1572536583, -1573452385, -1574352788, -1575233942, -1576092574, -1576926600, -1577732933, -1578507896, + -1579248680, -1579952850, -1580617181, -1581238194, -1581812847, -1582338764, -1582813204, -1583232638, -1583593989, + -1583895045, -1584133086, -1584304626, -1584406873, -1584437736, -1584394635, -1584274418, -1584074588, -1583793268, + -1583428030, -1582975737, -1582434279, -1581802744, -1581079400, -1580261338, -1579346529, -1578333908, -1577222011, + -1576009429, -1574695339, -1573278552, -1571757228, -1570130264, -1568398303, -1566561731, -1564618340, -1562566382, + -1560407784, -1558145041, -1555775754, -1553296829, -1550712057, -1548026396, -1545242289, -1542268350, -1538423280, + -1535025262, -1531395445, -1527591708, -1523601949, -1519416343, -1515026680, -1510422354, -1505596841, -1500543057, + -1495258714, -1489733930, -1483960441, -1477928294, -1471632952, -1465071334, -1458241898, -1451136236, -1443746092, + -1436060907, -1428079531, -1419805847, -1411239360, -1402373353, -1393199823, -1383713926, -1373917135, -1363813377, + -1353400513, -1342677100, -1331640941, -1320284636, -1308611825, -1296630892, -1284342674, -1271742396, -1258835954, + -1245628407, -1232122065, -1218316234, -1204224404, -1189846207, -1175175506, -1160242956, -1145031655, -1129564821, + -1113844775, -1097879736, -1081675373, -1065238433, -1048578417, -1031707925, -1014636539, -997375667, -979937295, + -962314566, -944532531, -926597437, -908531127, -890341534, -872033654, -853615925, -835103871, -816513734, + -797862235, -779149108, -760390220, -741599202, -722791848, -703980340, -685176354, -666389658, -647646244, + -628944722, -610316405, -591754523, -573282405, -554915396, -536666275, -518550375, -500581949, -482775076, + -465139339, -447692836, -430439482, -413418994, -396596647, -380036004, -363729221, -347677810, -331912032, + -316431125, -301242631, -286354637, -271795849, -257560706, -243655300, -230096441, -216894979, -204043835, + -191560528, -179450345, -167715723, -156363602, -145400931, -134832648, -124663143, -114896281, -105536276, + -96587551, -88053476, -79936384, -72238586, -64962154, -58107752, -51674659, -45661585, -40066372, + -34884913, -30111469, -25739290, -21759792, -18161914, -14933570, -12062384, -9522842, -7254663, + -5656627 }; +# else +# define MDCT_WINDOW_FS_32000_frame_ms_75 NULL +# endif +# ifdef SUBSET_FB +const Word32 MDCT_WINDOW_FS_48000_frame_ms_75[636] = { + 2204435, 2827689, 3443319, 4131102, 4878935, 5703040, 6599364, 7574899, 8628974, + 9768536, 10991420, 12304931, 13709256, 15207323, 16799052, 18489324, 20275023, 22160933, + 24148496, 26240076, 28435235, 30739604, 33150351, 35668955, 38294878, 41029635, 43871618, + 46825882, 49890883, 53068998, 56360550, 59766888, 63284768, 66918075, 70664961, 74526448, + 78503039, 82597929, 86807681, 91135031, 95578822, 100139618, 104816236, 109611835, 114523552, + 119554039, 124702224, 129967749, 135348514, 140848111, 146462751, 152193324, 158039847, 164002831, + 170078327, 176269443, 182573647, 188991411, 195521914, 202165741, 208918745, 215783357, 222755240, + 229832331, 237013913, 244302241, 251692923, 259188940, 266788795, 274490295, 282289304, 290186132, + 298175224, 306257381, 314430505, 322694044, 331045821, 339487261, 348012274, 356620678, 365310317, + 374079074, 382922254, 391842074, 400834178, 409898068, 419031270, 428232881, 437497913, 446828175, + 456219802, 465670981, 475178925, 484743299, 494357854, 504022976, 513735237, 523492799, 533292796, + 543136028, 553015990, 562931887, 572880536, 582859524, 592864355, 602896501, 612951047, 623027190, + 633121825, 643232873, 653354882, 663488155, 673627234, 683771323, 693918098, 704065470, 714207061, + 724344108, 734471992, 744587758, 754688429, 764774608, 774840295, 784884831, 794903648, 804894011, + 814851825, 824777247, 834664477, 844515260, 854327259, 864098094, 873822193, 883500485, 893125924, + 902697010, 912211002, 921668164, 931065070, 940403253, 949676961, 958885223, 968024298, 977093615, + 986086667, 995005058, 1003845874, 1012604766, 1021282611, 1029879030, 1038386135, 1046806723, 1055138039, + 1063379017, 1071528406, 1079585832, 1087546197, 1095410412, 1103175087, 1110839263, 1118400067, 1125861251, + 1133217689, 1140469587, 1147616705, 1154658548, 1161589135, 1168411456, 1175122212, 1181718798, 1188199640, + 1194567214, 1200817042, 1206950737, 1212967954, 1218868269, 1224650873, 1230316551, 1235861165, 1241285527, + 1246589565, 1251772729, 1256831629, 1261771016, 1266587826, 1271284733, 1275860443, 1280315823, 1284645497, + 1288852346, 1292933744, 1296889962, 1300722079, 1304434734, 1308025653, 1311497310, 1314848195, 1318076916, + 1321181451, 1324164254, 1327024207, 1329764950, 1332387885, 1334893025, 1337281173, 1339554157, 1341707740, + 1343747791, 1345671522, 1347481634, 1349179572, 1350764422, 1352239980, 1353613012, 1354873992, 1356030340, + 1357079368, 1358026526, 1358871638, 1359613742, 1360257791, 1360804083, 1361255397, 1361617096, 1361885808, + 1362062609, 1362151603, 1362153995, 1362072233, 1361909271, 1361666938, 1361347766, 1360955593, 1360489817, + 1359950116, 1359340101, 1358660855, 1357916180, 1357108339, 1356243400, 1355321087, 1354344570, 1353313776, + 1352230258, 1351093731, 1349909242, 1348677915, 1347405592, 1346095404, 1344750475, 1343369336, 1341955495, + 1340508098, 1339029437, 1337520955, 1335988076, 1334432030, 1332857982, 1331266254, 1329659151, 1328036799, + 1326403000, 1324757066, 1323104230, 1321446604, 1319787700, 1318127699, 1316471738, 1314818892, 1313173031, + 1311534229, 1309906742, 1308289975, 1306691587, 1305107061, 1303560954, 1302485706, 1300837265, 1299230148, + 1297667349, 1296147118, 1294669845, 1293233008, 1291838729, 1290486465, 1289178223, 1287911298, 1286686132, + 1285500617, 1284356733, 1283253302, 1282192039, 1281170798, 1280190420, 1279248602, 1278346792, 1277483349, + 1276659918, 1275874601, 1275128550, 1274419448, 1273748350, 1273113203, 1272515449, 1271953180, 1271427649, + 1270936717, 1270481540, 1270059928, 1269672963, 1269318382, 1268997326, 1268707731, 1268450837, 1268224483, + 1268029756, 1267864381, 1267729424, 1267622629, 1267545013, 1267494302, 1267471571, 1267474578, 1267504402, + 1267558747, 1267638603, 1267741668, 1267868942, 1268018115, 1268190239, 1268383008, 1268597404, 1268831071, + 1269084943, 1269356717, 1269647473, 1269954877, 1270279875, 1270620090, 1270976496, 1271346828, 1271732058, + 1272129716, 1272540744, 1272962829, 1273396990, 1273840888, 1274295422, 1274758248, 1275230417, 1275709517, + 1276196415, 1276688706, 1277187379, 1277690114, 1278197794, 1278707969, 1279221647, 1279736503, 1280253498, + -1280770244, -1281287656, -1281803343, -1282318265, -1282830085, -1283339807, -1283844964, -1284346432, -1284841866, + -1285332250, -1285815146, -1286291410, -1286758593, -1287217737, -1287666452, -1288105628, -1288532876, -1288949203, + -1289352245, -1289742931, -1290118731, -1290480607, -1290826232, -1291156571, -1291469183, -1291765004, -1292041634, + -1292300151, -1292538184, -1292756663, -1292953166, -1293128674, -1293280819, -1293410658, -1293515818, -1293597309, + -1293652773, -1293683213, -1293686282, -1293663081, -1293611326, -1293532118, -1293423149, -1293285472, -1293116803, + -1292918254, -1292687534, -1292425784, -1292130842, -1291804017, -1291443255, -1291049775, -1290621337, -1290159111, + -1289660945, -1289128099, -1288558489, -1287953483, -1287311252, -1286633366, -1285917866, -1285165943, -1284375393, + -1283547520, -1282680564, -1281776335, -1280833350, -1279853230, -1278833852, -1277776244, -1276678466, -1275542433, + -1274367185, -1273154903, -1271903726, -1270614321, -1269284275, -1267915816, -1266508671, -1265065178, -1263583140, + -1262063220, -1260504007, -1258908698, -1256628331, -1254761985, -1252853377, -1250881358, -1248844632, -1246741358, + -1244569594, -1242327619, -1240012651, -1237623600, -1235156149, -1232610864, -1229984110, -1227275248, -1224482272, + -1221606271, -1218642652, -1215591412, -1212448650, -1209213243, -1205881571, -1202455146, -1198931234, -1195311772, + -1191594196, -1187777826, -1183858288, -1179836046, -1175706321, -1171469469, -1167124636, -1162674694, -1158117379, + -1153454731, -1148683225, -1143802349, -1138808714, -1133702904, -1128481825, -1123149280, -1117704914, -1112149514, + -1106481061, -1100702139, -1094806903, -1088800296, -1082676113, -1076437274, -1070082677, -1063618676, -1057039488, + -1050351248, -1043548836, -1036634133, -1029608325, -1022475106, -1015230021, -1007878923, -1000415821, -992849913, + -985179219, -977404151, -969525479, -961538535, -953457394, -945280420, -936999272, -928626277, -920160734, + -911603664, -902957625, -894223210, -885402362, -876498250, -867508512, -858440255, -849293347, -840074392, + -830781521, -821419104, -811990901, -802499334, -792938179, -783315469, -773636100, -763901035, -754111866, + -744278025, -734399140, -724475975, -714510329, -704504133, -694460237, -684383382, -674277250, -664145566, + -653994294, -643817229, -633622219, -623410967, -613187040, -602954520, -592717105, -582476532, -572238350, + -562002979, -551770150, -541551921, -531349514, -521160592, -510991643, -500852505, -490735715, -480646079, + -470590740, -460574626, -450595871, -440662753, -430774557, -420941335, -411160195, -401435877, -391774603, + -382174290, -372642476, -363180190, -353786746, -344482765, -335253937, -326094163, -317034690, -308063867, + -299187762, -290405275, -281715156, -273134873, -264653333, -256282164, -248014183, -239853113, -231807709, + -223884020, -216073113, -208387006, -200816625, -193373144, -186056104, -178871459, -171808633, -164881963, + -158086310, -151426496, -144902306, -138514809, -132265008, -126156408, -120188845, -114364736, -108683712, + -103148269, -97758088, -92515604, -87420431, -82474860, -77678410, -73033188, -68538592, -64196501, + -60006167, -55969182, -52084610, -48353698, -44775286, -41350196, -38077002, -34956005, -31985545, + -29165263, -26493253, -23968386, -21588587, -19351751, -17255806, -15297341, -13474667, -11782386, + -10220076, -8778515, -7460996, -6246830, -5152154, -4038973 }; +# else +# define MDCT_WINDOW_FS_48000_frame_ms_75 NULL +# endif + +const Word32 *const LowDelayShapes_n960_7_5ms[5] = { + MDCT_WINDOW_FS_8000_frame_ms_75, MDCT_WINDOW_FS_16000_frame_ms_75, MDCT_WINDOW_FS_24000_frame_ms_75, MDCT_WINDOW_FS_32000_frame_ms_75, MDCT_WINDOW_FS_48000_frame_ms_75 }; +# else + +RAM_ALIGN const Word16 LowDelayShapes_n960_N60_7_5ms[106] = { + 71, 172, 330, 553, 847, 1216, 1662, 2187, 2790, 3472, 4229, 5058, 5953, 6909, + 7917, 8969, 10058, 11173, 12305, 13442, 14574, 15690, 16780, 17834, 18842, 19796, 20688, 21513, + 22265, 22940, 23534, 24047, 24477, 24825, 25093, 25284, 25402, 25453, 25444, 25384, 25281, 25144, + 24981, 24803, 24618, 24434, 24266, 24104, 23972, 23866, 23786, 23731, 23699, 23687, 23693, 23714, + 23749, 23793, 23845, 23901, -23959, -24016, -24068, -24113, -24148, -24170, -24176, -24164, -24131, -24075, + -23995, -23889, -23758, -23600, -23395, -23151, -22857, -22504, -22087, -21600, -21040, -20404, -19692, -18904, + -18044, -17116, -16128, -15086, -14001, -12884, -11746, -10598, -9455, -8328, -7232, -6179, -5184, -4258, + -3410, -2648, -1979, -1408, -938, -571, -304, -128}; + +RAM_ALIGN const Word16 LowDelayShapes_n960_N120_7_5ms[212] = { + 37, 64, 100, 145, 201, 268, 347, 438, 542, 659, 790, 934, 1091, 1263, + 1448, 1648, 1861, 2088, 2329, 2584, 2851, 3132, 3425, 3730, 4047, 4375, 4713, 5060, + 5417, 5781, 6154, 6533, 6918, 7308, 7702, 8100, 8500, 8902, 9304, 9706, 10106, 10504, + 10899, 11290, 11675, 12054, 12427, 12792, 13148, 13496, 13833, 14160, 14475, 14779, 15071, 15350, + 15616, 15868, 16107, 16331, 16542, 16737, 16919, 17085, 17237, 17375, 17498, 17607, 17702, 17782, + 17850, 17904, 17946, 17975, 17993, 18000, 17997, 17984, 17963, 17934, 17897, 17854, 17805, 17752, + 17695, 17634, 17571, 17506, 17440, 17375, 17310, 17246, 17190, 17128, 17071, 17019, 16972, 16930, + 16893, 16860, 16832, 16808, 16789, 16773, 16762, 16754, 16750, 16749, 16751, 16756, 16764, 16774, + 16786, 16800, 16816, 16833, 16852, 16871, 16891, 16911, -16932, -16952, -16972, -16991, -17010, -17027, + -17043, -17058, -17070, -17080, -17088, -17093, -17095, -17094, -17090, -17082, -17071, -17055, -17035, -17011, + -16983, -16950, -16913, -16871, -16824, -16773, -16717, -16657, -16581, -16503, -16417, -16322, -16218, -16104, + -15979, -15843, -15696, -15536, -15364, -15179, -14981, -14770, -14545, -14307, -14055, -13790, -13511, -13220, + -12916, -12599, -12271, -11932, -11582, -11223, -10855, -10478, -10095, -9705, -9310, -8910, -8508, -8103, + -7697, -7291, -6887, -6485, -6086, -5692, -5305, -4924, -4552, -4189, -3838, -3497, -3170, -2855, + -2555, -2270, -2001, -1748, -1511, -1292, -1090, -906, -740, -592, -462, -350, -256, -178, + -116, -68}; + +RAM_ALIGN const Word16 LowDelayShapes_n960_N180_7_5ms[318] = { + 54, 82, 114, 153, 198, 251, 312, 380, 458, 543, 638, 742, 856, 978, + 1111, 1253, 1405, 1566, 1738, 1920, 2111, 2313, 2525, 2747, 2980, 3222, 3474, 3737, + 4009, 4291, 4582, 4883, 5193, 5512, 5840, 6177, 6521, 6874, 7235, 7602, 7978, 8359, + 8747, 9141, 9541, 9947, 10357, 10772, 11191, 11614, 12041, 12470, 12902, 13336, 13771, 14208, + 14646, 15084, 15521, 15958, 16394, 16829, 17261, 17691, 18118, 18541, 18961, 19376, 19787, 20193, + 20593, 20987, 21375, 21757, 22131, 22499, 22858, 23210, 23553, 23889, 24215, 24532, 24841, 25140, + 25430, 25709, 25979, 26239, 26488, 26728, 26957, 27175, 27383, 27580, 27767, 27943, 28109, 28264, + 28409, 28543, 28666, 28779, 28882, 28975, 29058, 29132, 29195, 29250, 29295, 29332, 29359, 29379, + 29391, 29394, 29391, 29380, 29363, 29340, 29311, 29276, 29236, 29192, 29143, 29090, 29033, 28974, + 28911, 28846, 28779, 28710, 28640, 28569, 28498, 28426, 28355, 28284, 28214, 28145, 28090, 28019, + 27954, 27892, 27833, 27779, 27728, 27680, 27636, 27595, 27558, 27524, 27494, 27466, 27442, 27421, + 27403, 27387, 27375, 27365, 27358, 27353, 27351, 27351, 27354, 27358, 27365, 27373, 27383, 27395, + 27408, 27423, 27439, 27456, 27474, 27493, 27513, 27534, 27555, 27577, 27599, 27621, -27644, -27666, + -27688, -27710, -27731, -27752, -27772, -27792, -27810, -27827, -27844, -27859, -27872, -27884, -27894, -27903, + -27909, -27914, -27916, -27917, -27914, -27910, -27902, -27892, -27880, -27864, -27846, -27824, -27800, -27772, + -27741, -27707, -27670, -27629, -27585, -27538, -27487, -27433, -27375, -27315, -27251, -27182, -27096, -27014, + -26927, -26833, -26733, -26626, -26513, -26393, -26265, -26129, -25985, -25833, -25673, -25504, -25325, -25138, + -24941, -24735, -24520, -24294, -24060, -23815, -23561, -23296, -23022, -22738, -22445, -22141, -21829, -21507, + -21176, -20836, -20487, -20130, -19764, -19391, -19010, -18622, -18228, -17827, -17420, -17007, -16590, -16167, + -15741, -15311, -14877, -14441, -14003, -13563, -13122, -12680, -12238, -11796, -11356, -10917, -10481, -10047, + -9616, -9190, -8767, -8350, -7939, -7534, -7135, -6744, -6361, -5986, -5620, -5264, -4916, -4579, + -4253, -3937, -3632, -3339, -3058, -2788, -2530, -2285, -2053, -1833, -1626, -1432, -1251, -1083, + -929, -788, -659, -544, -441, -351, -272, -205, -148, -106}; + +RAM_ALIGN const Word16 LowDelayShapes_n960_N240_7_5ms[424] = { + 44, 61, 81, 103, 128, 156, 188, 224, 263, 306, 354, 405, 461, 521, + 586, 655, 728, 806, 889, 977, 1069, 1166, 1268, 1375, 1486, 1602, 1724, 1850, + 1981, 2117, 2258, 2404, 2555, 2711, 2871, 3037, 3207, 3382, 3562, 3747, 3936, 4130, + 4329, 4531, 4739, 4950, 5166, 5386, 5610, 5838, 6069, 6305, 6544, 6786, 7032, 7281, + 7533, 7788, 8046, 8307, 8570, 8836, 9104, 9374, 9646, 9920, 10196, 10474, 10753, 11033, + 11314, 11596, 11879, 12163, 12447, 12731, 13015, 13300, 13584, 13868, 14151, 14433, 14715, 14995, + 15274, 15552, 15828, 16103, 16375, 16646, 16914, 17180, 17444, 17704, 17963, 18218, 18470, 18719, + 18964, 19206, 19445, 19680, 19911, 20138, 20361, 20580, 20795, 21006, 21212, 21414, 21611, 21804, + 21992, 22175, 22354, 22527, 22696, 22860, 23018, 23172, 23321, 23464, 23603, 23736, 23864, 23988, + 24106, 24218, 24326, 24428, 24525, 24618, 24705, 24786, 24863, 24935, 25002, 25064, 25121, 25174, + 25221, 25264, 25303, 25336, 25366, 25391, 25412, 25428, 25441, 25450, 25455, 25456, 25454, 25448, + 25439, 25427, 25412, 25394, 25373, 25350, 25324, 25296, 25265, 25233, 25198, 25162, 25124, 25085, + 25045, 25003, 24960, 24916, 24871, 24826, 24780, 24734, 24688, 24641, 24595, 24548, 24502, 24457, + 24412, 24367, 24334, 24287, 24244, 24202, 24162, 24123, 24086, 24051, 24018, 23987, 23957, 23929, + 23902, 23878, 23855, 23833, 23813, 23795, 23778, 23763, 23749, 23737, 23726, 23717, 23709, 23702, + 23696, 23692, 23689, 23687, 23687, 23687, 23689, 23691, 23695, 23699, 23705, 23711, 23718, 23726, + 23735, 23744, 23754, 23764, 23776, 23787, 23799, 23812, 23825, 23838, 23852, 23866, 23880, 23894, + 23909, 23923, -23938, -23952, -23967, -23981, -23995, -24009, -24023, -24036, -24049, -24062, -24074, -24086, + -24097, -24108, -24118, -24128, -24137, -24145, -24152, -24158, -24164, -24168, -24172, -24175, -24176, -24177, + -24176, -24174, -24171, -24167, -24161, -24154, -24146, -24136, -24125, -24113, -24099, -24083, -24066, -24048, + -24028, -24006, -23983, -23958, -23932, -23904, -23874, -23843, -23810, -23775, -23739, -23701, -23662, -23621, + -23579, -23533, -23474, -23423, -23367, -23309, -23248, -23184, -23117, -23047, -22974, -22896, -22816, -22732, + -22643, -22551, -22455, -22355, -22251, -22143, -22030, -21913, -21791, -21665, -21534, -21399, -21259, -21114, + -20964, -20810, -20651, -20488, -20319, -20146, -19968, -19785, -19598, -19405, -19208, -19007, -18801, -18590, + -18375, -18156, -17932, -17704, -17472, -17236, -16996, -16752, -16505, -16254, -16000, -15743, -15482, -15219, + -14953, -14684, -14412, -14139, -13863, -13586, -13306, -13025, -12743, -12459, -12174, -11889, -11603, -11316, + -11029, -10742, -10455, -10168, -9882, -9597, -9313, -9029, -8748, -8467, -8189, -7912, -7638, -7367, + -7097, -6831, -6568, -6308, -6052, -5799, -5550, -5305, -5065, -4828, -4597, -4369, -4147, -3930, + -3718, -3511, -3310, -3113, -2923, -2738, -2559, -2386, -2219, -2057, -1902, -1753, -1610, -1474, + -1344, -1220, -1102, -991, -887, -788, -697, -611, -532, -459, -393, -332, -277, -228, + -184, -145, -111, -86}; + +RAM_ALIGN const Word16 LowDelayShapes_n960_N360_7_5ms[636] = { + 34, 43, 53, 63, 74, 87, 101, 116, 132, 149, 168, 188, 209, 232, + 256, 282, 309, 338, 368, 400, 434, 469, 506, 544, 584, 626, 669, 715, + 761, 810, 860, 912, 966, 1021, 1078, 1137, 1198, 1260, 1325, 1391, 1458, 1528, + 1599, 1673, 1747, 1824, 1903, 1983, 2065, 2149, 2235, 2322, 2411, 2502, 2595, 2690, + 2786, 2884, 2983, 3085, 3188, 3293, 3399, 3507, 3617, 3728, 3841, 3955, 4071, 4188, + 4307, 4428, 4550, 4673, 4798, 4924, 5051, 5180, 5310, 5442, 5574, 5708, 5843, 5979, + 6116, 6255, 6394, 6534, 6676, 6818, 6961, 7106, 7251, 7397, 7543, 7691, 7839, 7988, + 8137, 8288, 8438, 8590, 8741, 8894, 9046, 9199, 9353, 9507, 9661, 9815, 9969, 10124, + 10279, 10434, 10588, 10743, 10898, 11053, 11207, 11362, 11516, 11670, 11823, 11976, 12129, 12282, + 12434, 12585, 12736, 12886, 13036, 13185, 13333, 13481, 13628, 13774, 13919, 14064, 14207, 14349, + 14491, 14631, 14771, 14909, 15046, 15183, 15317, 15451, 15584, 15715, 15845, 15973, 16100, 16226, + 16350, 16473, 16595, 16715, 16833, 16950, 17065, 17179, 17292, 17402, 17511, 17619, 17724, 17829, + 17931, 18032, 18130, 18228, 18323, 18417, 18508, 18598, 18687, 18773, 18858, 18941, 19021, 19101, + 19178, 19253, 19327, 19398, 19468, 19536, 19602, 19666, 19729, 19789, 19847, 19904, 19959, 20012, + 20063, 20112, 20160, 20205, 20249, 20291, 20331, 20369, 20405, 20440, 20473, 20504, 20533, 20561, + 20587, 20611, 20634, 20654, 20674, 20691, 20707, 20722, 20735, 20746, 20756, 20764, 20771, 20777, + 20781, 20783, 20785, 20785, 20784, 20781, 20777, 20773, 20767, 20759, 20751, 20742, 20732, 20720, + 20708, 20695, 20681, 20666, 20650, 20633, 20616, 20598, 20579, 20560, 20540, 20519, 20498, 20477, + 20455, 20432, 20409, 20386, 20362, 20338, 20314, 20289, 20264, 20239, 20214, 20189, 20164, 20138, + 20113, 20088, 20063, 20037, 20012, 19988, 19963, 19939, 19914, 19891, 19874, 19849, 19825, 19801, + 19778, 19755, 19733, 19712, 19691, 19671, 19652, 19633, 19615, 19598, 19581, 19565, 19549, 19534, + 19520, 19506, 19493, 19480, 19468, 19457, 19446, 19436, 19426, 19417, 19408, 19400, 19393, 19386, + 19380, 19374, 19368, 19363, 19359, 19355, 19352, 19349, 19346, 19344, 19342, 19341, 19340, 19340, + 19340, 19341, 19341, 19343, 19344, 19346, 19348, 19351, 19354, 19357, 19361, 19365, 19369, 19373, + 19378, 19383, 19388, 19394, 19399, 19405, 19411, 19417, 19424, 19430, 19437, 19444, 19451, 19458, + 19466, 19473, 19481, 19488, 19496, 19504, 19512, 19519, 19527, 19535, -19543, -19551, -19559, -19567, + -19574, -19582, -19590, -19598, -19605, -19613, -19620, -19627, -19634, -19641, -19648, -19655, -19661, -19668, + -19674, -19680, -19686, -19691, -19696, -19701, -19706, -19711, -19715, -19719, -19723, -19726, -19729, -19732, + -19734, -19736, -19737, -19739, -19740, -19740, -19740, -19740, -19739, -19738, -19736, -19734, -19731, -19728, + -19725, -19721, -19716, -19711, -19706, -19700, -19693, -19686, -19679, -19671, -19662, -19653, -19643, -19632, + -19622, -19610, -19598, -19585, -19572, -19558, -19544, -19529, -19513, -19497, -19481, -19463, -19445, -19427, + -19408, -19388, -19368, -19347, -19325, -19303, -19281, -19258, -19234, -19209, -19175, -19146, -19117, -19087, + -19056, -19024, -18991, -18956, -18921, -18885, -18847, -18808, -18768, -18727, -18684, -18640, -18595, -18548, + -18500, -18451, -18400, -18348, -18294, -18239, -18182, -18124, -18064, -18003, -17940, -17875, -17809, -17741, + -17671, -17600, -17528, -17453, -17377, -17299, -17219, -17138, -17055, -16970, -16884, -16795, -16705, -16614, + -16520, -16425, -16328, -16230, -16129, -16027, -15923, -15818, -15711, -15602, -15491, -15379, -15265, -15150, + -15033, -14914, -14794, -14672, -14549, -14424, -14297, -14170, -14041, -13910, -13778, -13645, -13510, -13374, + -13237, -13099, -12959, -12819, -12677, -12534, -12390, -12245, -12099, -11952, -11805, -11656, -11507, -11357, + -11206, -11055, -10903, -10750, -10597, -10443, -10289, -10134, -9979, -9824, -9668, -9512, -9356, -9200, + -9044, -8888, -8732, -8575, -8419, -8263, -8108, -7952, -7797, -7642, -7488, -7334, -7181, -7028, + -6876, -6724, -6573, -6423, -6274, -6125, -5978, -5832, -5686, -5542, -5398, -5256, -5116, -4976, + -4838, -4701, -4565, -4431, -4299, -4168, -4038, -3911, -3784, -3660, -3537, -3416, -3297, -3180, + -3064, -2951, -2839, -2729, -2622, -2516, -2412, -2311, -2211, -2114, -2018, -1925, -1834, -1745, + -1658, -1574, -1492, -1412, -1334, -1258, -1185, -1114, -1046, -980, -916, -854, -795, -738, + -683, -631, -581, -533, -488, -445, -404, -366, -329, -295, -263, -233, -206, -180, + -156, -134, -114, -95, -79, -62}; + +const Word16 *const LowDelayShapes_n960_7_5ms[5] = { + LowDelayShapes_n960_N60_7_5ms, LowDelayShapes_n960_N120_7_5ms, LowDelayShapes_n960_N180_7_5ms, + LowDelayShapes_n960_N240_7_5ms, LowDelayShapes_n960_N360_7_5ms}; +# endif +#endif + +# ifdef ENABLE_HR_MODE +# ifdef SUBSET_NB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_8000_frame_ms_100[130] = { + -961400, -2849747, -6146069, -11183287, -18168658, -27159976, -38041614, -50544991, -64266305, + -78702302, -93275005, -107359966, -120331449, -131585369, -140567185, -146788394, -149841031, -149374845, + -145077849, -136659567, -123818556, -106218681, -83483575, -55188103, -20866242, 19967468, 67769998, + 122921021, 185652202, 255975827, 333632994, 418021593, 508185345, 602779388, 700109939, 798161092, + 894722554, 987480940, 1074157272, 1152645644, 1221190247, 1278509567, 1323911980, 1357388583, 1379593462, + 1391784272, 1395720478, 1393489246, 1387290092, 1379158144, 1370909958, 1362952657, 1356680081, 1351822616, + 1348129706, 1345389974, 1343434137, 1342132875, 1341380238, 1341082389, 1341146030, 1341475565, 1341976666, + 1342558820, 1343143270, 1343665484, 1344082633, 1344377759, 1344564351, 1344687981, 1344819951, 1345048163, + 1345462207, 1346140636, 1347141158, 1348493131, 1350195802, 1352216474, 1354492706, 1356936321, -1359440659, + -1361893201, -1364185723, -1366227332, -1367952395, -1369325253, -1370343007, -1371033982, -1371456025, -1371688758, + -1371823378, -1371949513, -1372139932, -1372441219, -1372867302, -1373401073, -1373998949, -1374594994, -1375108467, + -1375446347, -1375511619, -1375206190, -1374435007, -1373103717, -1371107592, -1368321163, -1364583182, -1359697421, + -1353439826, -1345583929, -1334252006, -1318640435, -1296625734, -1266042179, -1224814360, -1171299094, -1104589425, + -1024691930, -932610693, -830326556, -720679178, -607287900, -494260157, -385949065, -286606097, -199964372, + -128792415, -74461791, -36690922, -13577456 }; +# else +# define MDCT_WINDOW_FS_8000_frame_ms_100 NULL +# endif +# ifdef SUBSET_WB +Word32 MDCT_WINDOW_FS_16000_frame_ms_100[260] = { + -887375, -1872204, -3197066, -4988439, -7310990, -10227337, -13783209, -18021567, -22958367, + -28610377, -34970773, -42018157, -49718535, -58023758, -66873408, -76198163, -85910142, -95927481, + -106148057, -116469926, -126789141, -136988509, -146961365, -156599505, -165784108, -174413613, -182384155, + -189593925, -195957243, -201380750, -205787662, -209112092, -211278626, -212225338, -211904063, -210251417, + -207219014, -202758648, -196811500, -189330359, -180258003, -169532917, -157095614, -142881796, -126812734, + -108824087, -88825077, -66738724, -42479347, -15962398, 12903137, 44189991, 77985216, 114347898, + 153341694, 195002709, 239360583, 286415769, 336147305, 388513668, 443439084, 500814289, 560507827, + 622347139, 686131895, 751624641, 818548945, 886612081, 955480469, 1024792378, 1094174334, 1163233060, + 1231563801, 1298756609, 1364398281, 1428080024, 1489417472, 1548030726, 1603570137, 1655722624, 1704220353, + 1748832761, 1789380048, 1825732185, 1857837021, 1885694068, 1909350182, 1928926255, 1944599555, 1956591988, + 1965173692, 1970654814, 1973392048, 1973753741, 1972126549, 1968905622, 1964477747, 1959200677, 1953414096, + 1947497068, 1941982397, 1935699544, 1930081097, 1925079908, 1920651209, 1916744799, 1913315837, 1910318315, + 1907712617, 1905458724, 1903525160, 1901880657, 1900501434, 1899362031, 1898444320, 1897728470, 1897199074, + 1896837448, 1896629442, 1896556474, 1896603942, 1896753023, 1896988900, 1897292512, 1897649018, 1898040860, + 1898455207, 1898875282, 1899290274, 1899686952, 1900057791, 1900392969, 1900688703, 1900940068, 1901148890, + 1901315261, 1901446916, 1901549632, 1901635772, 1901716579, 1901808596, 1901925470, 1902085313, 1902301944, + 1902593430, 1902971628, 1903450623, 1904038863, 1904746055, 1905575675, 1906532421, 1907613683, 1908818837, + 1910139810, 1911570484, 1913097876, 1914709921, 1916389064, 1918119705, 1919880868, -1921655075, -1923419485, + -1925156475, -1926844779, -1928468408, -1930009301, -1931454857, -1932791495, -1934012556, -1935109403, -1936080977, + -1936924245, -1937643651, -1938242459, -1938730331, -1939115713, -1939412840, -1939633721, -1939796733, -1939915942, + -1940009808, -1940092245, -1940180131, -1940284940, -1940419293, -1940589100, -1940802279, -1941058948, -1941361010, + -1941703474, -1942082515, -1942488131, -1942912654, -1943342567, -1943766803, -1944168168, -1944533482, -1944844704, + -1945086561, -1945239453, -1945288139, -1945213300, -1944999989, -1944629251, -1944086772, -1943353711, -1942414745, + -1941250214, -1939842441, -1938166561, -1936199807, -1933912258, -1931274378, -1928248720, -1924799179, -1920884332, + -1916465285, -1911499377, -1905951172, -1899784891, -1891449639, -1882086102, -1871092605, -1858022426, -1842504117, + -1824150091, -1802570281, -1777395508, -1748280284, -1714926445, -1677106435, -1634654127, -1587483810, -1535592652, + -1479074019, -1418108336, -1352953154, -1283959587, -1211573312, -1136287716, -1058670176, -979383239, -899114678, + -818587615, -738568308, -659827651, -583145988, -509279027, -438949979, -372825231, -311497711, -255465040, + -205107348, -160673323, -122260482, -89825442, -63156242, -41931466, -25668784, -12980788 }; +# else +# define MDCT_WINDOW_FS_16000_frame_ms_100 NULL +# endif +# ifdef SUBSET_SSWB +Word32 MDCT_WINDOW_FS_24000_frame_ms_100[390] = { + -566705, -1110129, -1685050, -2404955, -3290604, -4357398, -5620992, -7096870, -8797110, + -10732247, -12913348, -15346312, -18033576, -20979359, -24186040, -27648819, -31361639, -35319387, + -39511857, -43926672, -48550894, -53369201, -58364329, -63516998, -68804773, -74208337, -79706124, + -85271101, -90877590, -96504202, -102123140, -107704698, -113222623, -118652834, -123968611, -129140789, + -134141816, -138946789, -143532274, -147872644, -151941696, -155718471, -159183810, -162313004, -165085094, + -167485061, -169496638, -171101141, -172281631, -173021519, -173310456, -173136812, -172483214, -171335676, + -169686052, -167521471, -164827705, -161591409, -157800875, -153444385, -148507128, -142973353, -136828628, + -130059834, -122650769, -114582255, -105836248, -96398529, -86248633, -75363800, -63725732, -51315501, + -38111620, -24094261, -9239538, 6471742, 23056447, 40536457, 58931280, 78254053, 98521159, + 119745967, 141936970, 165102364, 189247343, 214372698, 240474371, 267544931, 295575426, 324551903, + 354450456, 385246198, 416908490, 449403326, 482689758, 516718794, 551441284, 586801891, 622731215, + 659163373, 696029684, 733249762, 770740975, 808417324, 846185475, 883956761, 921637043, 959124688, + 996324031, 1033136615, 1069460208, 1105195788, 1140244773, 1174510921, 1207903363, 1240329980, 1271701586, + 1301936917, 1330960546, 1358704531, 1385106661, 1410109035, 1433668094, 1455740664, 1476295686, 1495314659, + 1512790051, 1528721877, 1543118961, 1555993720, 1567377327, 1577311901, 1585840140, 1593017314, 1598905809, + 1603572858, 1607094048, 1609553036, 1611038032, 1611639187, 1611445924, 1610554709, 1609062783, 1607062660, + 1604647205, 1601904616, 1598915994, 1595761439, 1592514651, 1589411075, 1586578699, 1582990467, 1579691165, + 1576632996, 1573802167, 1571187222, 1568776964, 1566559220, 1564523108, 1562656830, 1560950303, 1559392538, + 1557974462, 1556686097, 1555520279, 1554467590, 1553522528, 1552677071, 1551926380, 1551264122, 1550685851, + 1550186120, 1549761554, 1549406743, 1549118648, 1548892484, 1548724782, 1548611579, 1548548556, 1548532064, + 1548557824, 1548622043, 1548720068, 1548848512, 1549002557, 1549178941, 1549372811, 1549581179, 1549799479, + 1550025081, 1550253392, 1550482320, 1550707996, 1550928257, 1551140242, 1551341918, 1551531258, 1551707132, + 1551867783, 1552012940, 1552142171, 1552255441, 1552353722, 1552437360, 1552508729, 1552569181, 1552621341, + 1552667742, 1552711935, 1552756861, 1552806540, 1552864321, 1552934727, 1553021212, 1553127838, 1553258419, + 1553416594, 1553605935, 1553829154, 1554089545, 1554389317, 1554730803, 1555115388, 1555544621, 1556019161, + 1556539764, 1557105744, 1557717296, 1558373006, 1559071819, 1559811599, 1560590143, 1561405090, 1562252936, + 1563130339, 1564033457, 1564958401, 1565900358, 1566855101, 1567817123, -1568783655, -1569746861, -1570703949, + -1571649364, -1572578812, -1573487389, -1574371102, -1575225988, -1576048579, -1576835227, -1577583436, -1578290863, + -1578955234, -1579575367, -1580149723, -1580678399, -1581160607, -1581597028, -1581988259, -1582335808, -1582641029, + -1582906248, -1583133678, -1583326640, -1583487877, -1583621010, -1583729737, -1583817938, -1583889747, -1583948684, + -1583999362, -1584045193, -1584090279, -1584137621, -1584190841, -1584252527, -1584325358, -1584410718, -1584511035, + -1584626668, -1584758614, -1584906848, -1585070936, -1585250612, -1585444090, -1585650227, -1585866958, -1586092212, + -1586323072, -1586557326, -1586791018, -1587022005, -1587245580, -1587459040, -1587657701, -1587838487, -1587996409, + -1588128112, -1588228637, -1588294501, -1588320923, -1588304007, -1588239369, -1588123278, -1587951328, -1587719494, + -1587424275, -1587060842, -1586626176, -1586114863, -1585523601, -1584847006, -1584080761, -1583218674, -1582256132, + -1581185350, -1580001184, -1578694604, -1577258975, -1575684935, -1573964180, -1572086641, -1570043344, -1567823810, + -1565418712, -1562817696, -1560011672, -1556991601, -1553746487, -1550232508, -1545614483, -1540661510, -1535326382, + -1529347469, -1522634820, -1515104434, -1506662411, -1497214433, -1486667044, -1474925134, -1461899585, -1447505979, + -1431661421, -1414293801, -1395342396, -1374757780, -1352499694, -1328538688, -1302862307, -1275470003, -1246373968, + -1215606643, -1183212323, -1149244754, -1113774081, -1076886070, -1038679407, -999271421, -958778521, -917331256, + -875071965, -832168635, -788780400, -745078907, -701235665, -657439320, -613872407, -570722470, -528178104, + -486428392, -445655594, -406038238, -367747699, -330944214, -295781070, -262392452, -230898968, -201404745, + -173990773, -148716671, -125619512, -104711740, -85981071, -69390841, -54880490, -42367028, -31748204, + -22909680, -15677896, -8320202 }; +# else +# define MDCT_WINDOW_FS_24000_frame_ms_100 NULL +# endif +# ifdef SUBSET_SWB +Word32 MDCT_WINDOW_FS_32000_frame_ms_100[520] = { + -410329, -796949, -1136328, -1530183, -1997206, -2544529, -3177199, -3900727, -4721409, + -5644580, -6674901, -7816606, -9073542, -10449649, -11947654, -13568981, -15314575, -17185616, + -19183576, -21308469, -23557934, -25929130, -28420717, -31030313, -33753791, -36586142, -39522623, + -42558881, -45688908, -48905915, -52203334, -55573600, -59008578, -62500911, -66043225, -69627153, + -73242249, -76878656, -80528547, -84184130, -87834359, -91467738, -95074499, -98645962, -102173556, + -105646999, -109055430, -112389025, -115637823, -118792264, -121843979, -124784385, -127604158, -130292837, + -132842231, -135246333, -137497670, -139586545, -141504332, -143245396, -144804682, -146175706, -147351477, + -148325994, -149093197, -149646348, -149980871, -150094482, -149982174, -149636889, -149052616, -148226262, + -147155224, -145834061, -144257234, -142420419, -140318794, -137947501, -135302755, -132379903, -129173499, + -125677248, -121885484, -117793976, -113398013, -108690888, -103666131, -98316590, -92636250, -86619948, + -80260566, -73550172, -66480755, -59045143, -51237113, -43048956, -34473252, -25502546, -16127957, + -6341514, 3862818, 14491541, 25552349, 37053485, 49000846, 61399638, 74255377, 87574137, + 101359692, 115615618, 130345077, 145550314, 161232640, 177393068, 194030243, 211141818, 228724496, + 246775667, 265291298, 284263733, 303683434, 323542122, 343829307, 364532416, 385638632, 407133703, + 428999825, 451218622, 473771892, 496640476, 519799290, 543222449, 566886347, 590766871, 614834881, + 639060282, 663412218, 687860455, 712370477, 736908535, 761442526, 785938885, 810359699, 834668800, + 858831376, 882812136, 906573323, 930077938, 953289749, 976173461, 998692986, 1020814305, 1042504195, + 1063729320, 1084456529, 1104654343, 1124293323, 1143346837, 1161788685, 1179595571, 1196744793, 1213214499, + 1228990130, 1244053625, 1258390343, 1271989157, 1284842646, 1296945646, 1308295983, 1318894029, 1328742964, + 1337845893, 1346207620, 1353840346, 1360760354, 1366981286, 1372519590, 1377396138, 1381633759, 1385255026, + 1388285177, 1390752262, 1392686884, 1394119237, 1395082423, 1395609697, 1395734288, 1395488163, 1394907750, + 1394029226, 1392887172, 1391513953, 1389943438, 1388208885, 1386340921, 1384367440, 1382316364, 1380214130, + 1378106162, 1376182641, 1374415552, 1372026612, 1369811233, 1367710559, 1365724178, 1363849407, 1362082203, + 1360417744, 1358852161, 1357381258, 1356001076, 1354706993, 1353494673, 1352361089, 1351302228, 1350313689, + 1349392506, 1348535330, 1347739116, 1347001032, 1346317031, 1345686404, 1345105561, 1344572298, 1344084536, + 1343640384, 1343238137, 1342875748, 1342550922, 1342263301, 1342010831, 1341791477, 1341604203, 1341447356, + 1341320237, 1341220346, 1341146654, 1341097800, 1341072665, 1341069082, 1341085615, 1341121386, 1341174740, + 1341243587, 1341326852, 1341422956, 1341530950, 1341648658, 1341774344, 1341907686, 1342046793, 1342189996, + 1342336371, 1342484315, 1342633509, 1342781772, 1342928111, 1343072442, 1343213120, 1343349339, 1343480101, + 1343605189, 1343724192, 1343836029, 1343940104, 1344037064, 1344126250, 1344207727, 1344281010, 1344347228, + 1344406398, 1344458631, 1344504740, 1344545486, 1344582197, 1344614878, 1344644716, 1344673602, 1344702406, + 1344732123, 1344764116, 1344799913, 1344841581, 1344889533, 1344945396, 1345011275, 1345087987, 1345177164, + 1345279600, 1345397199, 1345531309, 1345682002, 1345850876, 1346039023, 1346247352, 1346476070, 1346725599, + 1346997017, 1347290788, 1347606421, 1347944342, 1348304546, 1348687326, 1349091759, 1349517389, 1349964590, + 1350432001, 1350919119, 1351424549, 1351948150, 1352488782, 1353044492, 1353614173, 1354196920, 1354791164, + 1355395130, 1356006741, 1356625062, 1357248513, 1357874066, -1358501833, -1359127963, -1359752565, -1360372594, + -1360986451, -1361593178, -1362190669, -1362777107, -1363350886, -1363911059, -1364456475, -1364985125, -1365495818, + -1365988370, -1366461329, -1366914145, -1367345397, -1367755425, -1368143727, -1368509329, -1368852492, -1369173176, + -1369471783, -1369747786, -1370001627, -1370234382, -1370446455, -1370638040, -1370810046, -1370963570, -1371100229, + -1371220085, -1371324505, -1371415420, -1371493639, -1371560818, -1371617789, -1371666695, -1371709196, -1371745710, + -1371778346, -1371808661, -1371838047, -1371867517, -1371897959, -1371931304, -1371968763, -1372010342, -1372057396, + -1372110702, -1372171094, -1372238686, -1372313498, -1372396683, -1372487751, -1372586771, -1372693072, -1372807320, + -1372928910, -1373056739, -1373190393, -1373329652, -1373473500, -1373621114, -1373770813, -1373922515, -1374075203, + -1374226645, -1374376513, -1374523166, -1374665655, -1374802265, -1374931057, -1375051695, -1375162397, -1375260925, + -1375346302, -1375416903, -1375471622, -1375508310, -1375525267, -1375521592, -1375495812, -1375445706, -1375370134, + -1375267707, -1375137383, -1374976617, -1374784711, -1374559999, -1374301455, -1374007032, -1373674676, -1373304076, + -1372892947, -1372439276, -1371941405, -1371397503, -1370805562, -1370163465, -1369467701, -1368717718, -1367909588, + -1367040649, -1366108055, -1365108685, -1364039842, -1362897427, -1361677778, -1360378277, -1358995048, -1357523990, + -1355961737, -1354304757, -1352549921, -1350693234, -1348731568, -1346663222, -1344488796, -1342151873, -1339094859, + -1335868526, -1332575618, -1329015998, -1325134514, -1320899332, -1316281926, -1311249778, -1305767783, -1299801189, + -1293316467, -1286278496, -1278652937, -1270407089, -1261510752, -1251931832, -1241641304, -1230612600, -1218823121, + -1206251778, -1192882032, -1178699247, -1163691417, -1147850058, -1131172617, -1113659053, -1095312137, -1076139342, + -1056154695, -1035374650, -1013817533, -991505119, -968465043, -944729088, -920331658, -895311402, -869713787, + -843580319, -816956722, -789893244, -762442487, -734669461, -706629428, -678385082, -649998064, -621530231, + -593051422, -564628794, -536328929, -508220768, -480373259, -452855166, -425735746, -399081503, -372957401, + -347428629, -322556345, -298398778, -275013415, -252453167, -230765335, -209993816, -190178661, -171354066, + -153547820, -136781064, -121069202, -106422336, -92843298, -80326106, -68858674, -58425411, -49003701, + -40559788, -33054527, -26453090, -20722011, -15806421, -11453718, -6043487 }; +# else +# define MDCT_WINDOW_FS_32000_frame_ms_100 NULL +# endif +# ifdef SUBSET_FB +Word32 MDCT_WINDOW_FS_48000_frame_ms_100[780] = { + -260941, -512326, -694531, -879311, -1080918, -1308853, -1562751, -1845827, -2158684, + -2503004, -2880077, -3290946, -3737685, -4221002, -4742864, -5303548, -5904756, -6546614, + -7230857, -7957740, -8729060, -9544323, -10404756, -11309433, -12259734, -13255019, -14296724, + -15384139, -16518209, -17697344, -18921986, -20190385, -21503384, -22859520, -24259194, -25700342, + -27183029, -28705009, -30266328, -31864635, -33500032, -35169872, -36873876, -38609380, -40375887, + -42170731, -43993030, -45839524, -47709533, -49600244, -51511244, -53439376, -55383757, -57340675, + -59308752, -61284610, -63267293, -65253972, -67243943, -69233263, -71220507, -73201745, -75175694, + -77138930, -79090353, -81026756, -82947219, -84848184, -86728232, -88583507, -90412766, -92212306, + -93980997, -95715499, -97414829, -99075933, -100697747, -102276727, -103811934, -105299541, -106738717, + -108126346, -109462104, -110743333, -111969072, -113135967, -114242829, -115286640, -116267230, -117181898, + -118030913, -118811562, -119523250, -120163192, -120730923, -121223904, -121641755, -121981772, -122243774, + -122425704, -122528356, -122549198, -122488317, -122342868, -122112204, -121794056, -121388712, -120894363, + -120311595, -119637953, -118873094, -118014671, -117062760, -116014831, -114871079, -113629173, -112289425, + -110849719, -109309933, -107667532, -105922420, -104072007, -102115976, -100051888, -97879875, -95597465, + -93204875, -90699195, -88080200, -85345024, -82492843, -79520968, -76429175, -73215366, -69879179, + -66417490, -62829616, -59111848, -55264005, -51283182, -47168943, -42918760, -38531620, -34004372, + -29336594, -24525462, -19570192, -14467231, -9215895, -3812888, 1741410, 7449630, 13312759, + 19333517, 25513103, 31854549, 38357631, 45024786, 51855914, 58853769, 66018789, 73353520, + 80857218, 88531868, 96377212, 104395033, 112584867, 120948431, 129484622, 138194897, 147077806, + 156134120, 165362222, 174762717, 184333381, 194074737, 203984869, 214063752, 224308471, 234717970, + 245288658, 256019674, 266907692, 277950967, 289145264, 300489211, 311977987, 323609345, 335378203, + 347280982, 359312288, 371469093, 383745604, 396138434, 408640853, 421247404, 433950689, 446746484, + 459627611, 472589454, 485624370, 498725842, 511885724, 525097999, 538353697, 551646906, 564968308, + 578310445, 591664155, 605022969, 618377829, 631721846, 645044713, 658338326, 671592921, 684801497, + 697954218, 711043692, 724059806, 736994360, 749837478, 762581648, 775216823, 787735715, 800128161, + 812386829, 824502387, 836468309, 848275065, 859915578, 871380881, 882663894, 893755956, 904651429, + 915341669, 925821650, 936083534, 946122397, 955931903, 965507514, 974842174, 983932079, 992771963, + 1001359538, 1009689065, 1017758097, 1025562027, 1033099052, 1040366302, 1047363095, 1054086968, 1060539102, + 1066717272, 1072622704, 1078255082, 1083616279, 1088705978, 1093526428, 1098077639, 1102363841, 1106387711, + 1110154526, 1113666093, 1116927603, 1119941829, 1122715077, 1125251563, 1127558143, 1129638911, 1131501374, + 1133150240, 1134593560, 1135837167, 1136890075, 1137758087, 1138450616, 1138974310, 1139338430, 1139549551, + 1139617253, 1139547254, 1139350624, 1139033981, 1138607794, 1138078811, 1137457063, 1136748191, 1135963275, + 1135107610, 1134191756, 1133220410, 1132203794, 1131145038, 1130056206, 1128938553, 1127804154, 1126651875, + 1125505224, 1124387956, 1123424960, 1122502936, 1121204059, 1119950632, 1118742198, 1117576653, 1116454214, + 1115372925, 1114332841, 1113331819, 1112370092, 1111445403, 1110557933, 1109705650, 1108888492, 1108104203, + 1107353139, 1106633126, 1105944161, 1105284140, 1104653414, 1104049906, 1103473745, 1102922793, 1102397465, + 1101895930, 1101418393, 1100962642, 1100529407, 1100117107, 1099725702, 1099353203, 1099000764, 1098666499, + 1098350488, 1098051309, 1097769862, 1097504226, 1097255015, 1097020632, 1096801846, 1096597180, 1096407228, + 1096230254, 1096067339, 1095917048, 1095779800, 1095654043, 1095540974, 1095438919, 1095348396, 1095268166, + 1095199173, 1095139611, 1095090409, 1095050175, 1095019519, 1094996963, 1094983471, 1094977391, 1094979525, + 1094988385, 1095004796, 1095027271, 1095056499, 1095090869, 1095131425, 1095176627, 1095227052, 1095281232, + 1095340201, 1095402343, 1095468278, 1095536534, 1095608171, 1095681620, 1095757514, 1095834402, 1095913392, + 1095992947, 1096073625, 1096154019, 1096235421, 1096316155, 1096396797, 1096476293, 1096555751, 1096633346, + 1096710075, 1096784773, 1096858327, 1096929351, 1096998877, 1097065514, 1097130458, 1097192392, 1097252182, + 1097308660, 1097363134, 1097414177, 1097462864, 1097508260, 1097551529, 1097591240, 1097628824, 1097663320, + 1097695680, 1097724878, 1097752577, 1097777519, 1097800889, 1097821938, 1097842083, 1097860192, 1097877707, + 1097893767, 1097909925, 1097925238, 1097941056, 1097956579, 1097973457, 1097990704, 1098009705, 1098029761, + 1098052600, 1098077182, 1098104865, 1098135087, 1098169468, 1098206820, 1098248699, 1098294539, 1098345796, + 1098401373, 1098462829, 1098529452, 1098602617, 1098681182, 1098766743, 1098858507, 1098957729, 1099063375, + 1099176931, 1099297350, 1099425943, 1099561602, 1099705648, 1099857107, 1100017184, 1100184629, 1100360829, + 1100544624, 1100737006, 1100936785, 1101145313, 1101361273, 1101585583, 1101817094, 1102057069, 1102303875, + 1102558446, 1102819734, 1103088684, 1103363640, 1103645734, 1103933619, 1104228082, 1104527573, 1104833025, + 1105142974, 1105458288, 1105777328, 1106100968, 1106427742, 1106758401, 1107091175, 1107426928, 1107764262, + 1108103811, 1108443736, 1108785137, -1109126464, -1109468075, -1109808418, -1110148595, -1110486758, -1110823540, + -1111157536, -1111489609, -1111817975, -1112143382, -1112464352, -1112781755, -1113093934, -1113401755, -1113703734, + -1114000803, -1114291390, -1114576277, -1114854097, -1115125982, -1115390248, -1115647841, -1115897690, -1116140732, + -1116375302, -1116602670, -1116821661, -1117033199, -1117235935, -1117431235, -1117617882, -1117796873, -1117967024, + -1118129738, -1118283734, -1118430232, -1118568236, -1118699084, -1118821642, -1118937239, -1119044805, -1119145850, + -1119239316, -1119326479, -1119406526, -1119481081, -1119548979, -1119611618, -1119668271, -1119720525, -1119767262, + -1119809963, -1119848051, -1119883112, -1119913933, -1119942166, -1119967238, -1119990533, -1120010991, -1120030373, + -1120047967, -1120065185, -1120081021, -1120097158, -1120112780, -1120129265, -1120145650, -1120163521, -1120181998, + -1120202553, -1120224032, -1120247880, -1120273333, -1120301601, -1120331401, -1120364428, -1120399639, -1120438004, + -1120478543, -1120522718, -1120569068, -1120618782, -1120670906, -1120726540, -1120784227, -1120845302, -1120908575, + -1120974930, -1121043024, -1121114079, -1121186673, -1121261863, -1121338234, -1121416691, -1121496045, -1121577316, + -1121658638, -1121741144, -1121823756, -1121907065, -1121989354, -1122071945, -1122153400, -1122234287, -1122313032, + -1122390771, -1122466015, -1122539413, -1122609356, -1122676929, -1122740622, -1122801070, -1122856613, -1122908312, + -1122954661, -1122996249, -1123031496, -1123061471, -1123084522, -1123101354, -1123110442, -1123112631, -1123106394, + -1123092556, -1123069422, -1123037982, -1122996721, -1122946267, -1122885196, -1122814464, -1122732221, -1122639444, + -1122534864, -1122419021, -1122290207, -1122149656, -1121995788, -1121829044, -1121647967, -1121453676, -1121244410, + -1121020792, -1120781333, -1120526836, -1120255693, -1119968555, -1119663488, -1119341437, -1119000986, -1118642248, + -1118263342, -1117865480, -1117446686, -1117006965, -1116544763, -1116060878, -1115553126, -1115021782, -1114465065, + -1113883468, -1113274918, -1112639632, -1111975615, -1111283324, -1110560756, -1109808026, -1109023086, -1108206431, + -1107355953, -1106471748, -1105551963, -1104596956, -1103604680, -1102575570, -1101507722, -1100401422, -1099254985, + -1098068882, -1096841318, -1095572135, -1093824443, -1092028958, -1090297711, -1088504795, -1086622918, -1084627237, + -1082515433, -1080275819, -1077903929, -1075390736, -1072729748, -1069911131, -1066927638, -1063770248, -1060430896, + -1056901504, -1053173546, -1049238310, -1045087876, -1040714437, -1036109920, -1031267875, -1026179775, -1020838674, + -1015237521, -1009370093, -1003230227, -996813209, -990113245, -983126698, -975849235, -968277852, -960408557, + -952239544, -943768000, -934993585, -925915442, -916534205, -906849190, -896862428, -886574831, -875990255, + -865111684, -853943783, -842489873, -830755484, -818745230, -806465779, -793923840, -781127868, -768084617, + -754803973, -741294413, -727567055, -713632929, -699502178, -685184041, -670691428, -656036019, -641230326, + -626286760, -611223511, -596053211, -580789367, -565447177, -550042966, -534590207, -519104101, -503600887, + -488098220, -472611780, -457157918, -441752495, -426412611, -411154642, -395995557, -380951672, -366040108, + -351277307, -336679493, -322262126, -308041137, -294032383, -280251079, -266711613, -253427888, -240414233, + -227684137, -215250748, -203125310, -191319486, -179843288, -168707738, -157921160, -147492810, -137428529, + -127735992, -118418783, -109483185, -100930269, -92764786, -84984919, -77594007, -70587122, -63966522, + -57723857, -51860743, -46364893, -41238076, -36463273, -32043815, -27956560, -24209143, -20769591, + -17655994, -14819879, -12293428, -9917917, -7494462, -3886267 }; +# else +# define MDCT_WINDOW_FS_48000_frame_ms_100 NULL +# endif + +# ifdef PACK_MDCT_WINDOWS +RAM_ALIGN const Word16 * LowDelayShapes_n960[6]; +# else +RAM_ALIGN const Word32 *const LowDelayShapes_n960[6] = { MDCT_WINDOW_FS_8000_frame_ms_100, MDCT_WINDOW_FS_16000_frame_ms_100, + MDCT_WINDOW_FS_24000_frame_ms_100, MDCT_WINDOW_FS_32000_frame_ms_100, + MDCT_WINDOW_FS_48000_frame_ms_100, NULL }; +# endif + +#else +RAM_ALIGN const Word16 *const LowDelayShapes_n960[6] = {LowDelayShapes_n960_N80, LowDelayShapes_n960_N160, + LowDelayShapes_n960_N240, LowDelayShapes_n960_N320, + LowDelayShapes_n960_N480, NULL}; +#endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 LowDelayShapes_n960_len_5ms[6] = {70, 140, 210, 280, 420, 840}; +# else +RAM_ALIGN const Word16 LowDelayShapes_n960_len_5ms[5] = {70, 140, 210, 280, 420}; +# endif + +RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes_5ms[NUM_SAMP_FREQ] = {10, + 20, + 30, + 40, + 60 +# ifdef ENABLE_HR_MODE + , 120 +# endif +}; + +# ifdef ENABLE_HR_MODE +# ifdef SUBSET_NB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_8000_frame_ms_25[40] = { + 9151354, 37109627, 83712740, 151998210, 242715442, 354150912, 482126354, 620379048, + 761296862, 896901837, 1019922302, 1124767307, 1208223590, 1269735636, 1311202326, 1336324669, + 1349655864, 1355605615, 1357680847, 1358157082, -1358157082, -1357680847, -1355605615, -1349655864, + -1336324669, -1311202326, -1269735636, -1208223590, -1124767307, -1019922302, -896901837, -761296862, + -620379048, -482126354, -354150912, -242715442, -151998210, -83712740, -37109627, -9151354}; +# else +# define MDCT_WINDOW_FS_8000_frame_ms_25 NULL +# endif +# ifdef SUBSET_WB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_16000_frame_ms_25[80] = { + 9151337, 23138265, 42763907, 68767772, 101782534, 142300433, 190643613, 246939893, 311105303, + 382834448, 461599452, 546657840, 637069348, 731721202, 829361019, 928636120, 1028137675, 1126447891, + 1222188210, 1314066414, 1400920509, 1481757333, 1555784035, 1622430811, 1681363664, 1732486397, 1775931558, + 1812040689, 1841334847, 1864477074, 1882229157, 1895405578, 1904827946, 1911283293, 1915489337, 1918069115, + 1919536352, 1920291661, 1920628396, 1920745966, -1920745966, -1920628396, -1920291661, -1919536352, -1918069115, + -1915489337, -1911283293, -1904827946, -1895405578, -1882229157, -1864477074, -1841334847, -1812040689, -1775931558, + -1732486397, -1681363664, -1622430811, -1555784035, -1481757333, -1400920509, -1314066414, -1222188210, -1126447891, + -1028137675, -928636120, -829361019, -731721202, -637069348, -546657840, -461599452, -382834448, -311105303, + -246939893, -190643613, -142300433, -101782534, -68767772, -42763907, -23138265, -9151337 }; +# else +# define MDCT_WINDOW_FS_16000_frame_ms_25 NULL +# endif +# ifdef SUBSET_SSWB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_24000_frame_ms_25[120] = { + 6100899, 12864132, 21489409, 32196712, 45171875, 60580072, 78565098, 99246695, 122717635, + 149041013, 178247915, 210335558, 245265970, 282965259, 323323502, 366195270, 411400805, 458727828, + 507933969, 558749783, 610882290, 664019005, 717832373, 771984525, 826132286, 879932323, 933046345, + 985146249, 1035919114, 1085071930, 1132335985, 1177470792, 1220267489, 1260551623, 1298185265, 1333068386, + 1365139469, 1394375330, 1420790145, 1444433697, 1465388876, 1483768499, 1499711524, 1513378754, 1524948163, + 1534609980, 1542561681, 1549003060, 1554131535, 1558137849, 1561202310, 1563491688, 1565156852, 1566331192, + 1567129839, 1567649635, 1567969785, 1568153080, 1568247554, 1568288448, -1568288448, -1568247554, -1568153080, + -1567969785, -1567649635, -1567129839, -1566331192, -1565156852, -1563491688, -1561202310, -1558137849, -1554131535, + -1549003060, -1542561681, -1534609980, -1524948163, -1513378754, -1499711524, -1483768499, -1465388876, -1444433697, + -1420790145, -1394375330, -1365139469, -1333068386, -1298185265, -1260551623, -1220267489, -1177470792, -1132335985, + -1085071930, -1035919114, -985146249, -933046345, -879932323, -826132286, -771984525, -717832373, -664019005, + -610882290, -558749783, -507933969, -458727828, -411400805, -366195270, -323323502, -282965259, -245265970, + -210335558, -178247915, -149041013, -122717635, -99246695, -78565098, -60580072, -45171875, -32196712, + -21489409, -12864132, -6100899 }; +# else +# define MDCT_WINDOW_FS_24000_frame_ms_25 NULL +# endif +# ifdef SUBSET_SWB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_32000_frame_ms_25[160] = { + 4575679, 8767860, 13776210, 19722611, 26689435, 34747238, 43959497, 54383445, 66069923, + 79062931, 93399091, 109107106, 126207257, 144710958, 164620379, 185928150, 208617151, 232660396, + 258021008, 284652300, 312497943, 341492250, 371560541, 402619617, 434578316, 467338167, 500794115, + 534835326, 569346062, 604206611, 639294264, 674484335, 709651210, 744669409, 779414654, 813764938, + 847601565, 880810169, 913281687, 944913281, 975609194, 1005281536, 1033850982, 1061247376, 1087410241, + 1112289173, 1135844126, 1158045581, 1178874586, 1198322683, 1216391705, 1233093455, 1248449271, 1262489470, + 1275252698, 1286785178, 1297139874, 1306375586, 1314555990, 1321748631, 1328023899, 1333453999, 1338111934, + 1342070524, 1345401476, 1348174521, 1350456644, 1352311405, 1353798377, 1354972700, 1355884752, 1356579954, + 1357098688, 1357476324, 1357743362, 1357925654, 1358044707, 1358118045, 1358159612, 1358180205, -1358180205, + -1358159612, -1358118045, -1358044707, -1357925654, -1357743362, -1357476324, -1357098688, -1356579954, -1355884752, + -1354972700, -1353798377, -1352311405, -1350456644, -1348174521, -1345401476, -1342070524, -1338111934, -1333453999, + -1328023899, -1321748631, -1314555990, -1306375586, -1297139874, -1286785178, -1275252698, -1262489470, -1248449271, + -1233093455, -1216391705, -1198322683, -1178874586, -1158045581, -1135844126, -1112289173, -1087410241, -1061247376, + -1033850982, -1005281536, -975609194, -944913281, -913281687, -880810169, -847601565, -813764938, -779414654, + -744669409, -709651210, -674484335, -639294264, -604206611, -569346062, -534835326, -500794115, -467338167, + -434578316, -402619617, -371560541, -341492250, -312497943, -284652300, -258021008, -232660396, -208617151, + -185928150, -164620379, -144710958, -126207257, -109107106, -93399091, -79062931, -66069923, -54383445, + -43959497, -34747238, -26689435, -19722611, -13776210, -8767860, -4575679 }; +# else +# define MDCT_WINDOW_FS_32000_frame_ms_25 NULL +# endif +# ifdef SUBSET_FB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_48000_frame_ms_25[240] = { + 3050456, 5295536, 7753004, 10501942, 13578229, 17006497, 20806969, 24997575, 29594719, + 34613583, 40068237, 45971662, 52335732, 59171174, 66487516, 74293042, 82594732, 91398213, + 100707709, 110526001, 120854381, 131692624, 143038956, 154890033, 167240926, 180085109, 193414462, + 207219271, 221488240, 236208515, 251365705, 266943917, 282925795, 299292569, 316024108, 333098980, + 350494519, 368186897, 386151203, 404361529, 422791056, 441412148, 460196455, 479115006, 498138325, + 517236531, 536379451, 555536738, 574677975, 593772799, 612791011, 631702693, 650478321, 669088878, + 687505964, 705701904, 723649854, 741323899, 758699157, 775751861, 792459455, 808800673, 824755609, + 840305794, 855434253, 870125559, 884365881, 898143024, 911446458, 924267340, 936598527, 948434586, + 959771781, 970608068, 980943072, 990778052, 1000115868, 1008960932, 1017319150, 1025197865, 1032605778, + 1039552878, 1046050356, 1052110513, 1057746665, 1062973048, 1067804709, 1072257401, 1076347473, 1080091765, + 1083507488, 1086612119, 1089423293, 1091958692, 1094235940, 1096272508, 1098085614, 1099692137, 1101108528, + 1102350741, 1103434158, 1104373531, 1105182928, 1105875693, 1106464406, 1106960861, 1107376047, 1107720140, + 1108002502, 1108231688, 1108415463, 1108560820, 1108674010, 1108760573, 1108825377, 1108872657, 1108906059, + 1108928685, 1108943144, 1108951592, -1108951592, -1108943144, -1108928685, -1108906059, -1108872657, -1108825377, + -1108760573, -1108674010, -1108560820, -1108415463, -1108231688, -1108002502, -1107720140, -1107376047, -1106960861, + -1106464406, -1105875693, -1105182928, -1104373531, -1103434158, -1102350741, -1101108528, -1099692137, -1098085614, + -1096272508, -1094235940, -1091958692, -1089423293, -1086612119, -1083507488, -1080091765, -1076347473, -1072257401, + -1067804709, -1062973048, -1057746665, -1052110513, -1046050356, -1039552878, -1032605778, -1025197865, -1017319150, + -1008960932, -1000115868, -990778052, -980943072, -970608068, -959771781, -948434586, -936598527, -924267340, + -911446458, -898143024, -884365881, -870125559, -855434253, -840305794, -824755609, -808800673, -792459455, + -775751861, -758699157, -741323899, -723649854, -705701904, -687505964, -669088878, -650478321, -631702693, + -612791011, -593772799, -574677975, -555536738, -536379451, -517236531, -498138325, -479115006, -460196455, + -441412148, -422791056, -404361529, -386151203, -368186897, -350494519, -333098980, -316024108, -299292569, + -282925795, -266943917, -251365705, -236208515, -221488240, -207219271, -193414462, -180085109, -167240926, + -154890033, -143038956, -131692624, -120854381, -110526001, -100707709, -91398213, -82594732, -74293042, + -66487516, -59171174, -52335732, -45971662, -40068237, -34613583, -29594719, -24997575, -20806969, + -17006497, -13578229, -10501942, -7753004, -5295536, -3050456 }; +# else +# define MDCT_WINDOW_FS_48000_frame_ms_25 NULL +# endif +#endif + +# ifdef ENABLE_HR_MODE +# ifdef SUBSET_NB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_8000_frame_ms_50[70] = { + 1912909, 7335521, 18325724, 36910622, 64974178, 104198418, 155981280, 221305462, 300589079, + 393635120, 499623692, 617106989, 744004208, 877694270, 1015162828, 1153137249, 1288239038, 1417150998, + 1536791945, 1644447880, 1737962977, 1815833349, 1877263804, 1922306058, 1951829636, 1967471711, 1971505676, + 1966594148, 1955602246, 1941502114, 1927310881, 1914588900, 1905592841, 1900063224, 1897652925, 1897963170, + 1900562354, 1904988644, 1910750498, 1917333371, -1924208315, -1930837552, -1936677590, -1941187989, -1943846368, + -1944164165, -1941697923, -1936063536, -1926966575, -1914246866, -1895468226, -1869147188, -1832534703, -1783214725, + -1719263259, -1639330989, -1542778136, -1429960741, -1302431717, -1162827131, -1014564422, -861762630, -709123640, + -561741289, -424627691, -302165309, -197940066, -114914393, -55161222, -18600494 }; +# else +# define MDCT_WINDOW_FS_8000_frame_ms_50 NULL +# endif +# ifdef SUBSET_WB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_16000_frame_ms_50[140] = { + 834388, 2023133, 3917156, 6701705, 10565521, 15685856, 22235650, 30384241, 40286022, + 52095516, 65948322, 81967398, 100265346, 120927126, 144016301, 169574495, 197607091, 228098907, + 261006859, 296253144, 333742048, 373344049, 414902600, 458235462, 503129294, 549353006, 596652543, + 644762423, 693401311, 742277119, 791098023, 839557429, 887360048, 934211532, 979820668, 1023922652, + 1066251747, 1106569674, 1144656239, 1180316465, 1213396318, 1243758349, 1271300584, 1295946391, 1317664404, + 1336461856, 1352374790, 1365487180, 1375907723, 1383780765, 1389286272, 1392625157, 1394020824, 1393712039, + 1391944281, 1388970703, 1385052050, 1380450904, 1375432870, 1370255673, 1365493257, 1360311818, 1355815371, + 1351987330, 1348809662, 1346259072, 1344307938, 1342925268, 1342077528, 1341729312, 1341843769, 1342382749, + 1343306801, 1344575110, 1346145481, 1347974400, 1350017219, 1352228384, 1354561632, 1356970112, -1359406807, + -1361823903, -1364173707, -1366408059, -1368478813, -1370338075, -1371938535, -1373233878, -1374179166, -1374731135, + -1374848407, -1374491689, -1373624022, -1372211199, -1370222452, -1367631371, -1364416934, -1360564607, -1356067324, + -1350921653, -1344029735, -1336226439, -1326949476, -1315967441, -1303050661, -1287981322, -1270565808, -1250633190, + -1228037147, -1202659404, -1174406746, -1143219019, -1109079369, -1072015866, -1032110341, -989504343, -944386484, + -896992664, -847599093, -796504062, -744037160, -690570612, -636495945, -582226621, -528203723, -474881089, + -422717084, -372160937, -323635430, -277529378, -234193138, -193941056, -157058932, -123809989, -94431397, + -69117849, -47990622, -31057417, -18172622, -9019056 }; +# else +# define MDCT_WINDOW_FS_16000_frame_ms_50 NULL +# endif +# ifdef SUBSET_SSWB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_24000_frame_ms_50[210] = { + 564151, 1104419, 1865494, 2894039, 4235165, 5932159, 8033172, 10580362, 13613959, + 17177173, 21310358, 26053470, 31441110, 37512859, 44302113, 51841191, 60158985, 69285016, + 79244161, 90055834, 101740044, 114307277, 127770768, 142131061, 157390145, 173545185, 190584386, + 208498576, 227265343, 246867205, 267275117, 288457873, 310382420, 333006130, 356286886, 380173162, + 404613227, 429551030, 454926373, 480676280, 506737023, 533041379, 559520739, 586104532, 612719819, + 639298867, 665764101, 692044954, 718069120, 743765156, 769064062, 793893410, 818192510, 841895640, + 864939671, 887267243, 908824605, 929558785, 949422426, 968375342, 986383128, 1003413393, 1019433821, + 1034427350, 1048371873, 1061257817, 1073079562, 1083838763, 1093544388, 1102204732, 1109843920, 1116483171, + 1122153769, 1126889366, 1130731703, 1133726105, 1135920322, 1137368676, 1138125139, 1138249333, 1137797435, + 1136832092, 1135413661, 1133604477, 1131468200, 1129067483, 1126468580, 1123733695, 1120926768, 1118121453, + 1115661504, 1112733456, 1110039679, 1107592275, 1105388417, 1103424195, 1101694785, 1100194540, 1098917076, + 1097855409, 1097002014, 1096348961, 1095887953, 1095610427, 1095507566, 1095570351, 1095789547, 1096155725, + 1096659227, 1097290187, 1098038501, 1098893850, 1099845706, 1100883348, 1101995893, 1103172315, 1104401472, + 1105672121, 1106972938, 1108292669, -1109619302, -1110942189, -1112249205, -1113528884, -1114769580, -1115959638, + -1117087420, -1118141328, -1119109856, -1119981619, -1120745408, -1121390225, -1121905319, -1122280224, -1122504764, + -1122569097, -1122463704, -1122179448, -1121707579, -1121039818, -1120168401, -1119086203, -1117786804, -1116264645, + -1114515111, -1112534671, -1110320979, -1107872954, -1105190944, -1102290376, -1098369607, -1094349090, -1089850335, + -1084803470, -1079152632, -1072839707, -1065811535, -1058014404, -1049399648, -1039922082, -1029539502, -1018216878, + -1005918442, -992617105, -978287110, -962909114, -946468188, -928955851, -910372331, -890723372, -870025772, + -848301812, -825588219, -801924529, -777362543, -751959302, -725776798, -698887464, -671358557, -643273732, + -614708529, -585759042, -556515015, -527075925, -497538887, -468010517, -438598442, -409412725, -380564000, + -352163661, -324321484, -297140687, -270721761, -245158912, -220540161, -196946958, -174455223, -153136078, + -133056674, -114280750, -96868231, -80874056, -66345855, -53320577, -41820223, -31847346, -23380692, + -16371397, -10739000, -6256916 }; +# else +# define MDCT_WINDOW_FS_24000_frame_ms_50 NULL +# endif +# ifdef SUBSET_SWB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_32000_frame_ms_50[280] = { + 882763, 1521118, 2358563, 3425984, 4762639, 6395771, 8362131, 10689006, 13418692, + 16576000, 20193865, 24299300, 28928500, 34104984, 39865074, 46229302, 53228467, 60887056, + 69236180, 78292965, 88087142, 98634050, 109959733, 122081209, 135019424, 148782425, 163392710, + 178855011, 195181305, 212377526, 230451659, 249395809, 269219382, 289915225, 311477904, 333897457, + 357170677, 381274098, 406199848, 431929301, 458441926, 485710203, 513718369, 542430861, 571822196, + 601857045, 632504350, 663719412, 695470641, 727711424, 760403450, 793496784, 826949741, 860710772, + 894737379, 928972875, 963373530, 997882662, 1032450522, 1067021806, 1101552211, 1135977909, 1170251366, + 1204317771, 1238127288, 1271622131, 1304759595, 1337479850, 1369736833, 1401482421, 1432674669, 1463259078, + 1493196881, 1522440628, 1550955893, 1578698536, 1605635690, 1631726882, 1656947594, 1681264014, 1704659250, + 1727103999, 1748576205, 1769054798, 1788533700, 1806990078, 1824418644, 1840812466, 1856170505, 1870488908, + 1883781944, 1896047096, 1907297858, 1917548829, 1926819646, 1935123035, 1942490021, 1948939055, 1954502859, + 1959211322, 1963101243, 1966202102, 1968559589, 1970206964, 1971189283, 1971546464, 1971324022, 1970559672, + 1969305529, 1967600289, 1965492731, 1963026251, 1960251018, 1957207403, 1953949375, 1950518787, 1946965804, + 1943332468, 1939669743, 1936018211, 1933074896, 1929170790, 1925511708, 1922091318, 1918913458, 1915970631, + 1913265545, 1910789617, 1908544525, 1906520767, 1904719178, 1903129502, 1901751868, 1900575443, 1899599816, + 1898813735, 1898216400, 1897796234, 1897552155, 1897472330, 1897555435, 1897789418, 1898172732, 1898693091, + 1899348726, 1900127098, 1901026195, 1902033230, 1903145941, 1904351313, 1905646871, 1907019391, 1908466229, + 1909973977, 1911539869, 1913150363, 1914802598, 1916482920, 1918188394, 1919905292, -1921630629, -1923350609, + -1925062194, -1926751519, -1928415501, -1930040212, -1931622556, -1933148598, -1934615259, -1936008644, -1937325739, + -1938552759, -1939686835, -1940714349, -1941632651, -1942428351, -1943099088, -1943631764, -1944024336, -1944264050, + -1944349204, -1944267410, -1944017355, -1943587051, -1942975631, -1942171601, -1941174620, -1939973809, -1938569504, + -1936951577, -1935121231, -1933069293, -1930798023, -1928299406, -1925576914, -1922623868, -1919445128, -1916035514, + -1912401346, -1908538993, -1903226832, -1898165387, -1892651677, -1886636702, -1880083188, -1872945708, -1865186866, + -1856760038, -1847633035, -1837760249, -1827110036, -1815644193, -1803335041, -1790145270, -1776055593, -1761033530, + -1745059396, -1728108424, -1710167501, -1691212572, -1671237793, -1650226116, -1628174600, -1605075941, -1580936677, + -1555754529, -1529546654, -1502320930, -1474101256, -1444909741, -1414780308, -1383738492, -1351831573, -1319095487, + -1285577912, -1251324682, -1216394344, -1180827594, -1144691880, -1108040592, -1070930654, -1033434550, -995621142, + -957552560, -919309430, -880954958, -842572374, -804234470, -766025822, -728021485, -690307576, -652960034, + -616065598, -579699451, -543943367, -508866771, -474546527, -441046910, -408438534, -376778154, -346129113, + -316541929, -288074358, -260771792, -234687576, -209863469, -186348825, -164181088, -143404068, -124048067, + -106147028, -89718620, -74780184, -61329654, -49360094, -38842904, -29739589, -21991349, -15513048, + -10180154 }; +# else +# define MDCT_WINDOW_FS_32000_frame_ms_50 NULL +# endif +# ifdef SUBSET_FB +RAM_ALIGN const Word32 MDCT_WINDOW_FS_48000_frame_ms_50[420] = { + 641452, 963468, 1344309, 1798864, 2336113, 2963727, 3690212, 4523143, 5470567, + 6539876, 7738462, 9075874, 10560639, 12200013, 14000287, 15968479, 18112467, 20440430, + 22959153, 25675517, 28597257, 31731569, 35084700, 38662325, 42471171, 46518292, 50811124, + 55354756, 60154720, 65216952, 70547205, 76150562, 82031461, 88195322, 94647798, 101393537, + 108435354, 115776449, 123420676, 131372779, 139634617, 148207504, 157093536, 166295700, 175815910, + 185653595, 195807761, 206278987, 217068929, 228177014, 239600679, 251337195, 263385931, 275745715, + 288413583, 301384760, 314655039, 328222340, 342083665, 356233498, 370664518, 385372123, 400351243, + 415596618, 431100575, 446855251, 462853492, 479088256, 495551477, 512233512, 529124734, 546216403, + 563499351, 580963667, 598598648, 616393743, 634338212, 652420945, 670630244, 688955012, 707384418, + 725906000, 744507517, 763176760, 781901922, 800670867, 819470287, 838286395, 857107788, 875922821, + 894718707, 913481313, 932196408, 950852353, 969437415, 987938553, 1006342043, 1024635125, 1042806406, + 1060844237, 1078734559, 1096464849, 1114023247, 1131399453, 1148583332, 1165562052, 1182324038, 1198858240, + 1215154081, 1231201466, 1246990634, 1262512157, 1277756598, 1292714571, 1307377034, 1321735176, 1335781943, + 1349510011, 1362912058, 1375982854, 1388718627, 1401109382, 1413152613, 1424839949, 1436168435, 1447135603, + 1457737882, 1467971469, 1477831821, 1487317959, 1496429995, 1505166563, 1513525606, 1521507797, 1529115290, + 1536350460, 1543213224, 1549704472, 1555827692, 1561587898, 1566989343, 1572034920, 1576728782, 1581076815, + 1585086027, 1588761389, 1592109107, 1595136511, 1597852394, 1600264963, 1602381209, 1604209606, 1605759882, + 1607041997, 1608065019, 1608838122, 1609371538, 1609676596, 1609763199, 1609640908, 1609320042, 1608811796, + 1608127979, 1607278811, 1606274326, 1605125864, 1603845218, 1602443629, 1600931810, 1599320348, 1597621250, + 1595846595, 1594007402, 1592114826, 1590179414, 1588213076, 1586227163, 1584231653, 1582234964, 1580207977, + 1578973545, 1576735799, 1574650444, 1572657612, 1570752789, 1568935343, 1567204832, 1565560739, 1564002460, + 1562529304, 1561140497, 1559835185, 1558612434, 1557471243, 1556410547, 1555429220, 1554526076, 1553699872, + 1552949321, 1552273100, 1551669839, 1551138129, 1550676530, 1550283581, 1549957792, 1549697644, 1549501594, + 1549368091, 1549295559, 1549282400, 1549326998, 1549427723, 1549582929, 1549790946, 1550050083, 1550358639, + 1550714889, 1551117086, 1551563464, 1552052237, 1552581604, 1553149738, 1553754795, 1554394911, 1555068212, + 1555772800, 1556506765, 1557268182, 1558055112, 1558865609, 1559697712, 1560549450, 1561418844, 1562303905, + 1563202640, 1564113045, 1565033113, 1565960825, 1566894119, 1567830370, -1568770400, -1569707772, -1570643299, + -1571574337, -1572498793, -1573414613, -1574319739, -1575212113, -1576089676, -1576950365, -1577792121, -1578612885, + -1579410602, -1580183223, -1580928704, -1581645010, -1582330113, -1582982003, -1583598681, -1584178165, -1584718489, + -1585217707, -1585673898, -1586085163, -1586449622, -1586765423, -1587030743, -1587243787, -1587402781, -1587505982, + -1587551679, -1587538195, -1587463877, -1587327103, -1587126293, -1586859906, -1586526431, -1586124397, -1585652387, + -1585109032, -1584493010, -1583803053, -1583037961, -1582196603, -1581277917, -1580280911, -1579204680, -1578048412, + -1576811384, -1575492968, -1574092640, -1572609980, -1571044684, -1569396562, -1567665543, -1565851670, -1563955090, + -1561975794, -1559909960, -1557699231, -1554579493, -1551951859, -1549122074, -1546121016, -1542941389, -1539572601, + -1536005010, -1532229275, -1528234689, -1524011122, -1519548313, -1514837211, -1509868869, -1504633300, -1499121016, + -1493323395, -1487232726, -1480841309, -1474140699, -1467123022, -1459782240, -1452112311, -1444106817, -1435759114, + -1427063276, -1418015155, -1408610288, -1398843935, -1388711462, -1378209682, -1367336091, -1356088102, -1344462791, + -1332458664, -1320075617, -1307313612, -1294173092, -1280654545, -1266760135, -1252493498, -1237857298, -1222855659, + -1207493934, -1191778366, -1175716859, -1159315327, -1142581197, -1125524357, -1108155092, -1090483582, -1072519662, + -1054273467, -1035757912, -1016986859, -997971439, -978723129, -959255645, -939584189, -919723670, -899686034, + -879484158, -859140109, -838667380, -818082710, -797402257, -776643501, -755824703, -734962210, -714073915, + -693179322, -672297393, -651446511, -630646657, -609917124, -589277150, -568746490, -548345449, -528092326, + -508008241, -488111645, -468421183, -448956496, -429734434, -410773661, -392090517, -373702005, -355624406, + -337873208, -320463322, -303409145, -286724555, -270422942, -254517317, -239020241, -223943842, -209300003, + -195100311, -181356034, -168078124, -155277193, -142963461, -131146681, -119836028, -109039985, -98766166, + -89021184, -79810417, -71137840, -63005796, -55414797, -48363340, -41847826, -35862016, -30397367, + -25442735, -20983937, -17003804, -13482292, -10414308, -8112352 }; +# else +# define MDCT_WINDOW_FS_48000_frame_ms_50 NULL +# endif +#endif + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 *const LowDelayShapes_n960_5ms[6] = { + MDCT_WINDOW_FS_8000_frame_ms_50, MDCT_WINDOW_FS_16000_frame_ms_50, MDCT_WINDOW_FS_24000_frame_ms_50, MDCT_WINDOW_FS_32000_frame_ms_50, MDCT_WINDOW_FS_48000_frame_ms_50, NULL }; +#else +RAM_ALIGN const Word16 *const LowDelayShapes_n960_5ms[6] = {LowDelayShapes_n960_N40_5ms, LowDelayShapes_n960_N80_5ms, + LowDelayShapes_n960_N120_5ms, LowDelayShapes_n960_N160_5ms, + LowDelayShapes_n960_N240_5ms, NULL}; +#endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 LowDelayShapes_n960_len_2_5ms[6] = {40, 80, 120, 160, 240, 480}; +# else +RAM_ALIGN const Word16 LowDelayShapes_n960_len_2_5ms[5] = {40, 80, 120, 160, 240}; +# endif + +RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes_2_5ms[NUM_SAMP_FREQ] = {0, + 0, + 0, + 0, + 0 +}; + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 *const LowDelayShapes_n960_2_5ms[6] = { + MDCT_WINDOW_FS_8000_frame_ms_25, MDCT_WINDOW_FS_16000_frame_ms_25, MDCT_WINDOW_FS_24000_frame_ms_25, MDCT_WINDOW_FS_32000_frame_ms_25, MDCT_WINDOW_FS_48000_frame_ms_25, NULL }; +#else +RAM_ALIGN const Word16 *const LowDelayShapes_n960_2_5ms[6] = { + LowDelayShapes_n960_N40_2_5ms, LowDelayShapes_n960_N80_2_5ms, LowDelayShapes_n960_N120_2_5ms, + LowDelayShapes_n960_N160_2_5ms, LowDelayShapes_n960_N240_2_5ms, NULL}; +#endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k_HR[6] = {12, 74, 137, 200, 266, 333}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k_HR[6] = {74, 137, 200, 266, 333, 400}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_96k_HR[6] = {12, 74, 137, 200, 266, 333}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_96k_HR[6] = {74, 137, 200, 266, 333, 400}; +RAM_ALIGN const Word16 *const tns_subdiv_startfreq_HR[2] = {tns_subdiv_startfreq_48k_HR, tns_subdiv_startfreq_96k_HR}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_HR[2] = {tns_subdiv_stopfreq_48k_HR, tns_subdiv_stopfreq_96k_HR}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k_5ms_HR[4] = {6, 53, 100, 150}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k_5ms_HR[4] = {53, 100, 150, 200}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_96k_5ms_HR[4] = {6, 53, 100, 150}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_96k_5ms_HR[4] = {53, 100, 150, 200}; + +RAM_ALIGN const Word16 *const tns_subdiv_startfreq_5ms_HR[2] = {tns_subdiv_startfreq_48k_5ms_HR, + tns_subdiv_startfreq_96k_5ms_HR}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_5ms_HR[2] = {tns_subdiv_stopfreq_48k_5ms_HR, + tns_subdiv_stopfreq_96k_5ms_HR}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k_2_5ms_HR[2] = {3, 51}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k_2_5ms_HR[2] = {51, 100}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_96k_2_5ms_HR[2] = {3, 51}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_96k_2_5ms_HR[2] = {51, 100}; + +RAM_ALIGN const Word16 *const tns_subdiv_startfreq_2_5ms_HR[2] = {tns_subdiv_startfreq_48k_2_5ms_HR, + tns_subdiv_startfreq_96k_2_5ms_HR}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_2_5ms_HR[2] = {tns_subdiv_stopfreq_48k_2_5ms_HR, + tns_subdiv_stopfreq_96k_2_5ms_HR}; +# endif + + +RAM_ALIGN const Word16 tns_subdiv_startfreq_8k[6] = {12, 34, 57, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_8k[6] = {34, 57, 80, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_16k[6] = {12, 61, 110, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_16k[6] = {61, 110, 160, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_24k[6] = {12, 88, 164, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_24k[6] = {88, 164, 240, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_32k[6] = {12, 61, 110, 160, 213, 266}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_32k[6] = {61, 110, 160, 213, 266, 320}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k[6] = {12, 74, 137, 200, 266, 333}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k[6] = {74, 137, 200, 266, 333, 400}; +RAM_ALIGN const Word16 *const tns_subdiv_startfreq[MAX_BW_BANDS_NUMBER] = { + tns_subdiv_startfreq_8k, tns_subdiv_startfreq_16k, tns_subdiv_startfreq_24k, tns_subdiv_startfreq_32k, + tns_subdiv_startfreq_48k}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq[MAX_BW_BANDS_NUMBER] = { + tns_subdiv_stopfreq_8k, tns_subdiv_stopfreq_16k, tns_subdiv_stopfreq_24k, tns_subdiv_stopfreq_32k, + tns_subdiv_stopfreq_48k}; + + +RAM_ALIGN const Word16 tns_subdiv_startfreq_8k_5ms[4] = {6, 23, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_8k_5ms[4] = {23, 40, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_16k_5ms[4] = {6, 43, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_16k_5ms[4] = {43, 80, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_24k_5ms[4] = {6, 63, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_24k_5ms[4] = {63, 120, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_32k_5ms[4] = {6, 43, 80, 120}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_32k_5ms[4] = {43, 80, 120, 160}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k_5ms[4] = {6, 53, 100, 150}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k_5ms[4] = {53, 100, 150, 200}; +RAM_ALIGN const Word16 *const tns_subdiv_startfreq_5ms[MAX_BW_BANDS_NUMBER] = { + tns_subdiv_startfreq_8k_5ms, tns_subdiv_startfreq_16k_5ms, tns_subdiv_startfreq_24k_5ms, + tns_subdiv_startfreq_32k_5ms, tns_subdiv_startfreq_48k_5ms}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_5ms[MAX_BW_BANDS_NUMBER] = { + tns_subdiv_stopfreq_8k_5ms, tns_subdiv_stopfreq_16k_5ms, tns_subdiv_stopfreq_24k_5ms, tns_subdiv_stopfreq_32k_5ms, + tns_subdiv_stopfreq_48k_5ms}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_8k_2_5ms[2] = {3, 11}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_8k_2_5ms[2] = {11, 20}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_16k_2_5ms[2] = {3, 21}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_16k_2_5ms[2] = {21, 40}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_24k_2_5ms[2] = {3, 31}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_24k_2_5ms[2] = {31, 60}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_32k_2_5ms[2] = {3, 41}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_32k_2_5ms[2] = {41, 80}; +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k_2_5ms[2] = {3, 51}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k_2_5ms[2] = {51, 100}; + +RAM_ALIGN const Word16 *const tns_subdiv_startfreq_2_5ms[MAX_BW_BANDS_NUMBER] = { + tns_subdiv_startfreq_8k_2_5ms, tns_subdiv_startfreq_16k_2_5ms, tns_subdiv_startfreq_24k_2_5ms, + tns_subdiv_startfreq_32k_2_5ms, tns_subdiv_startfreq_48k_2_5ms}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_2_5ms[MAX_BW_BANDS_NUMBER] = { + tns_subdiv_stopfreq_8k_2_5ms, tns_subdiv_stopfreq_16k_2_5ms, tns_subdiv_stopfreq_24k_2_5ms, + tns_subdiv_stopfreq_32k_2_5ms, tns_subdiv_stopfreq_48k_2_5ms}; + +#ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 tns_subdiv_startfreq_8k_7_5ms[6] = {9, 26, 43, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_8k_7_5ms[6] = {26, 43, 60, 0, 0, 0}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_16k_7_5ms[6] = {9, 46, 83, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_16k_7_5ms[6] = {46, 83, 120, 0, 0, 0}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_24k_7_5ms[6] = {9, 66, 123, 0, 0, 0}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_24k_7_5ms[6] = {66, 123, 180, 0, 0, 0}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_32k_7_5ms[6] = {9, 46, 82, 120, 159, 200}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_32k_7_5ms[6] = {46, 82, 120, 159, 200, 240}; + +RAM_ALIGN const Word16 tns_subdiv_startfreq_48k_7_5ms[6] = {9, 56, 103, 150, 200, 250}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_48k_7_5ms[6] = {56, 103, 150, 200, 250, 300}; + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 tns_subdiv_startfreq_96k_7_5ms[6] = {9, 56, 103, 150, 200, 250}; +RAM_ALIGN const Word16 tns_subdiv_stopfreq_96k_7_5ms[6] = {56, 103, 150, 200, 250, 300}; +# endif + +RAM_ALIGN const Word16 *const tns_subdiv_startfreq_7_5ms[] = { + tns_subdiv_startfreq_8k_7_5ms, tns_subdiv_startfreq_16k_7_5ms, tns_subdiv_startfreq_24k_7_5ms, + tns_subdiv_startfreq_32k_7_5ms, tns_subdiv_startfreq_48k_7_5ms +# ifdef ENABLE_HR_MODE + , tns_subdiv_startfreq_96k_7_5ms +# endif +}; +RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_7_5ms[] = { + tns_subdiv_stopfreq_8k_7_5ms, tns_subdiv_stopfreq_16k_7_5ms, tns_subdiv_stopfreq_24k_7_5ms, + tns_subdiv_stopfreq_32k_7_5ms, tns_subdiv_stopfreq_48k_7_5ms +# ifdef ENABLE_HR_MODE + , tns_subdiv_stopfreq_96k_7_5ms +# endif +}; +# endif + +RAM_ALIGN const Word16 Tab_esc_nb[4] = {0 << (NBITS_CONTEXT + NBITS_RATEQ), 1 << (NBITS_CONTEXT + NBITS_RATEQ), + 2 << (NBITS_CONTEXT + NBITS_RATEQ), 3 << (NBITS_CONTEXT + NBITS_RATEQ)}; +RAM_ALIGN const Word8 ari_spec_lookup[4096] = { + 0x01, 0x27, 0x07, 0x19, 0x16, 0x16, 0x1C, 0x16, 0x16, 0x16, 0x16, 0x1C, 0x1C, 0x1C, 0x22, 0x1F, 0x1F, 0x28, 0x2B, + 0x2E, 0x31, 0x34, 0x0E, 0x11, 0x24, 0x24, 0x24, 0x26, 0x00, 0x39, 0x26, 0x16, 0x00, 0x08, 0x09, 0x0B, 0x2F, 0x0E, + 0x0E, 0x11, 0x24, 0x24, 0x24, 0x26, 0x3B, 0x3B, 0x26, 0x16, 0x16, 0x1A, 0x2E, 0x1D, 0x1E, 0x20, 0x21, 0x23, 0x24, + 0x24, 0x24, 0x26, 0x00, 0x3B, 0x17, 0x16, 0x2E, 0x2E, 0x2D, 0x2F, 0x30, 0x32, 0x32, 0x12, 0x36, 0x36, 0x36, 0x26, + 0x3B, 0x3B, 0x3B, 0x16, 0x00, 0x3E, 0x3F, 0x03, 0x21, 0x02, 0x02, 0x3D, 0x14, 0x14, 0x14, 0x15, 0x3B, 0x3B, 0x27, + 0x1C, 0x1C, 0x3F, 0x3F, 0x03, 0x21, 0x02, 0x02, 0x3D, 0x26, 0x26, 0x26, 0x15, 0x3B, 0x3B, 0x27, 0x1C, 0x1C, 0x06, + 0x06, 0x06, 0x02, 0x12, 0x3D, 0x14, 0x15, 0x15, 0x15, 0x3B, 0x27, 0x27, 0x07, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x33, 0x33, 0x33, 0x35, 0x36, 0x14, 0x26, + 0x26, 0x39, 0x27, 0x27, 0x27, 0x07, 0x18, 0x22, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x38, 0x26, 0x39, 0x39, 0x3B, 0x07, 0x07, 0x07, 0x2A, + 0x2A, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x04, 0x04, 0x05, 0x15, 0x15, 0x3B, 0x07, 0x07, 0x07, 0x07, 0x19, 0x19, 0x19, 0x22, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x17, 0x17, 0x27, 0x07, 0x07, 0x07, 0x2A, 0x19, 0x19, 0x16, 0x1F, 0x1F, 0x27, 0x27, 0x27, 0x27, 0x07, 0x07, + 0x2A, 0x00, 0x19, 0x16, 0x16, 0x16, 0x1C, 0x22, 0x1F, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, + 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x28, 0x08, 0x09, 0x31, 0x31, 0x34, 0x11, 0x11, 0x11, 0x04, 0x00, + 0x14, 0x11, 0x3C, 0x28, 0x28, 0x08, 0x2B, 0x1B, 0x31, 0x31, 0x0E, 0x11, 0x11, 0x11, 0x24, 0x2A, 0x2A, 0x11, 0x39, + 0x39, 0x28, 0x08, 0x1A, 0x1B, 0x31, 0x0C, 0x0E, 0x11, 0x11, 0x11, 0x24, 0x00, 0x26, 0x24, 0x01, 0x08, 0x08, 0x2B, + 0x09, 0x0B, 0x31, 0x0C, 0x0E, 0x0E, 0x21, 0x32, 0x32, 0x32, 0x3D, 0x24, 0x27, 0x08, 0x08, 0x2B, 0x2E, 0x31, 0x34, + 0x1E, 0x0E, 0x0E, 0x21, 0x32, 0x32, 0x32, 0x32, 0x12, 0x19, 0x08, 0x08, 0x2B, 0x2E, 0x31, 0x34, 0x1E, 0x0E, 0x0E, + 0x12, 0x05, 0x05, 0x05, 0x3D, 0x12, 0x17, 0x2B, 0x2B, 0x2B, 0x09, 0x31, 0x34, 0x03, 0x0E, 0x0E, 0x32, 0x32, 0x32, + 0x32, 0x3D, 0x11, 0x18, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, + 0x2B, 0x2B, 0x2B, 0x2B, 0x09, 0x0B, 0x34, 0x34, 0x0E, 0x0E, 0x11, 0x3D, 0x3D, 0x3D, 0x36, 0x11, 0x27, 0x2D, 0x2D, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2C, 0x1B, 0x1D, + 0x34, 0x30, 0x34, 0x34, 0x11, 0x11, 0x11, 0x11, 0x02, 0x11, 0x07, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, + 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x09, 0x1B, 0x1B, 0x0C, 0x34, 0x0E, 0x0E, 0x3A, 0x29, + 0x29, 0x29, 0x06, 0x11, 0x25, 0x09, 0x09, 0x09, 0x1B, 0x0B, 0x31, 0x0C, 0x34, 0x0E, 0x0E, 0x0E, 0x32, 0x00, 0x35, + 0x11, 0x1C, 0x34, 0x34, 0x31, 0x34, 0x0C, 0x34, 0x1E, 0x0E, 0x0E, 0x11, 0x02, 0x02, 0x02, 0x26, 0x26, 0x22, 0x1F, + 0x22, 0x22, 0x1F, 0x1F, 0x1F, 0x1F, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x1F, 0x13, 0x2C, 0x2C, 0x3E, 0x1E, + 0x20, 0x3A, 0x23, 0x24, 0x24, 0x26, 0x00, 0x3B, 0x07, 0x07, 0x27, 0x22, 0x22, 0x2D, 0x2F, 0x30, 0x21, 0x23, 0x23, + 0x24, 0x26, 0x26, 0x26, 0x3B, 0x07, 0x07, 0x27, 0x22, 0x22, 0x3E, 0x1E, 0x0F, 0x32, 0x35, 0x35, 0x36, 0x15, 0x15, + 0x15, 0x3B, 0x07, 0x07, 0x07, 0x22, 0x1E, 0x1E, 0x30, 0x21, 0x3A, 0x12, 0x12, 0x38, 0x17, 0x17, 0x17, 0x3B, 0x07, + 0x07, 0x18, 0x22, 0x22, 0x06, 0x06, 0x3A, 0x35, 0x36, 0x36, 0x15, 0x3B, 0x3B, 0x3B, 0x27, 0x07, 0x07, 0x2A, 0x22, + 0x06, 0x06, 0x21, 0x3A, 0x35, 0x36, 0x3D, 0x15, 0x3B, 0x3B, 0x3B, 0x27, 0x07, 0x07, 0x2A, 0x22, 0x22, 0x33, 0x33, + 0x35, 0x36, 0x38, 0x38, 0x39, 0x27, 0x27, 0x27, 0x07, 0x2A, 0x2A, 0x19, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x04, 0x04, 0x04, 0x05, 0x17, 0x17, 0x27, 0x07, + 0x07, 0x07, 0x2A, 0x19, 0x19, 0x16, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05, 0x05, 0x05, 0x05, 0x39, 0x39, 0x27, 0x18, 0x18, 0x18, 0x2A, 0x16, 0x16, 0x1C, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x29, + 0x29, 0x29, 0x29, 0x27, 0x27, 0x07, 0x2A, 0x2A, 0x2A, 0x19, 0x1C, 0x1C, 0x1C, 0x1F, 0x1F, 0x29, 0x29, 0x29, 0x29, + 0x27, 0x27, 0x18, 0x19, 0x19, 0x19, 0x16, 0x1C, 0x1C, 0x22, 0x1F, 0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1C, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1F, 0x13, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x0B, 0x2F, 0x20, 0x32, 0x12, 0x12, 0x14, 0x15, 0x15, 0x15, 0x27, + 0x3B, 0x22, 0x1A, 0x1A, 0x1B, 0x1D, 0x1E, 0x21, 0x32, 0x12, 0x12, 0x14, 0x39, 0x39, 0x39, 0x3B, 0x3B, 0x22, 0x1B, + 0x1B, 0x0B, 0x0C, 0x30, 0x32, 0x3A, 0x3D, 0x3D, 0x38, 0x39, 0x39, 0x39, 0x3B, 0x27, 0x22, 0x2D, 0x2D, 0x0C, 0x1E, + 0x20, 0x02, 0x02, 0x3D, 0x26, 0x26, 0x26, 0x39, 0x00, 0x3B, 0x27, 0x22, 0x3F, 0x3F, 0x03, 0x20, 0x3A, 0x12, 0x12, + 0x14, 0x15, 0x15, 0x15, 0x3B, 0x27, 0x27, 0x07, 0x1F, 0x1F, 0x03, 0x03, 0x21, 0x3A, 0x12, 0x12, 0x14, 0x15, 0x15, + 0x15, 0x3B, 0x07, 0x07, 0x07, 0x1F, 0x06, 0x06, 0x33, 0x33, 0x35, 0x36, 0x36, 0x26, 0x39, 0x39, 0x39, 0x27, 0x07, + 0x07, 0x2A, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x33, 0x35, 0x35, 0x36, 0x38, 0x38, 0x39, 0x3B, 0x3B, 0x3B, 0x07, 0x18, 0x18, 0x19, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x04, 0x04, 0x04, 0x36, 0x15, + 0x15, 0x39, 0x27, 0x27, 0x27, 0x07, 0x2A, 0x2A, 0x16, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x05, 0x05, 0x05, 0x05, 0x17, 0x17, 0x3B, 0x07, 0x07, 0x07, 0x2A, + 0x16, 0x16, 0x1C, 0x1F, 0x1F, 0x04, 0x04, 0x04, 0x05, 0x17, 0x17, 0x27, 0x18, 0x18, 0x18, 0x19, 0x1C, 0x1C, 0x22, + 0x1F, 0x1F, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1C, 0x22, 0x22, 0x22, 0x1F, 0x1F, 0x1F, 0x1F, 0x13, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, + 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, + 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, + 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x10, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, + 0x3C, 0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x25, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x13, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x3C, 0x3C, 0x3C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x3C, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, + 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +RAM_ALIGN const UWord16 ari_spec_cumfreq[64][17] = { + {0, 1, 2, 177, 225, 226, 227, 336, 372, 543, 652, 699, 719, 768, 804, 824, 834}, + {0, 18, 44, 61, 71, 98, 135, 159, 175, 197, 229, 251, 265, 282, 308, 328, 341}, + {0, 71, 163, 212, 237, 318, 420, 481, 514, 556, 613, 652, 675, 697, 727, 749, 764}, + {0, 160, 290, 336, 354, 475, 598, 653, 677, 722, 777, 808, 823, 842, 866, 881, 890}, + {0, 71, 144, 177, 195, 266, 342, 385, 411, 445, 489, 519, 539, 559, 586, 607, 622}, + {0, 48, 108, 140, 159, 217, 285, 327, 354, 385, 427, 457, 478, 497, 524, 545, 561}, + {0, 138, 247, 290, 308, 419, 531, 584, 609, 655, 710, 742, 759, 780, 807, 825, 836}, + {0, 16, 40, 62, 79, 103, 139, 170, 195, 215, 245, 270, 290, 305, 327, 346, 362}, + {0, 579, 729, 741, 743, 897, 970, 980, 982, 996, 1007, 1010, 1011, 1014, 1017, 1018, 1019}, + {0, 398, 582, 607, 612, 788, 902, 925, 931, 956, 979, 987, 990, 996, 1002, 1005, 1007}, + {0, 13, 34, 52, 63, 83, 112, 134, 149, 163, 183, 199, 211, 221, 235, 247, 257}, + {0, 281, 464, 501, 510, 681, 820, 857, 867, 902, 938, 953, 959, 968, 978, 984, 987}, + {0, 198, 362, 408, 421, 575, 722, 773, 789, 832, 881, 905, 915, 928, 944, 954, 959}, + {0, 1, 2, 95, 139, 140, 141, 213, 251, 337, 407, 450, 475, 515, 551, 576, 592}, + {0, 133, 274, 338, 366, 483, 605, 664, 691, 730, 778, 807, 822, 837, 857, 870, 878}, + {0, 128, 253, 302, 320, 443, 577, 636, 659, 708, 767, 799, 814, 833, 857, 872, 881}, + {0, 1, 2, 25, 42, 43, 44, 67, 85, 105, 126, 144, 159, 174, 191, 205, 217}, + {0, 70, 166, 229, 267, 356, 468, 533, 569, 606, 653, 685, 705, 722, 745, 762, 774}, + {0, 55, 130, 175, 200, 268, 358, 416, 449, 488, 542, 581, 606, 628, 659, 683, 699}, + {0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, + {0, 34, 85, 123, 147, 196, 265, 317, 352, 386, 433, 470, 497, 518, 549, 574, 593}, + {0, 30, 73, 105, 127, 170, 229, 274, 305, 335, 377, 411, 436, 455, 483, 506, 524}, + {0, 9, 24, 38, 51, 65, 87, 108, 126, 139, 159, 177, 193, 204, 221, 236, 250}, + {0, 30, 74, 105, 125, 166, 224, 266, 294, 322, 361, 391, 413, 431, 457, 478, 494}, + {0, 15, 38, 58, 73, 95, 128, 156, 178, 196, 222, 245, 263, 276, 296, 314, 329}, + {0, 11, 28, 44, 57, 74, 100, 123, 142, 157, 179, 199, 216, 228, 246, 262, 276}, + {0, 448, 619, 639, 643, 821, 926, 944, 948, 971, 991, 998, 1000, 1005, 1010, 1012, 1013}, + {0, 332, 520, 549, 555, 741, 874, 903, 910, 940, 970, 981, 985, 991, 998, 1002, 1004}, + {0, 8, 21, 34, 45, 58, 78, 96, 112, 124, 141, 157, 170, 180, 194, 207, 219}, + {0, 239, 415, 457, 468, 631, 776, 820, 833, 872, 914, 933, 940, 951, 964, 971, 975}, + {0, 165, 310, 359, 375, 513, 652, 707, 727, 774, 828, 856, 868, 884, 904, 916, 923}, + {0, 3, 8, 13, 18, 23, 30, 37, 44, 48, 55, 62, 68, 72, 78, 84, 90}, + {0, 115, 237, 289, 311, 422, 547, 608, 635, 680, 737, 771, 788, 807, 832, 849, 859}, + {0, 107, 221, 272, 293, 399, 521, 582, 610, 656, 714, 749, 767, 787, 813, 831, 842}, + {0, 6, 16, 26, 35, 45, 60, 75, 89, 98, 112, 125, 137, 145, 157, 168, 178}, + {0, 72, 160, 210, 236, 320, 422, 482, 514, 555, 608, 644, 665, 685, 712, 732, 745}, + {0, 45, 108, 153, 183, 244, 327, 385, 421, 455, 502, 536, 559, 578, 605, 626, 641}, + {0, 1, 2, 9, 16, 17, 18, 26, 34, 40, 48, 55, 62, 68, 75, 82, 88}, + {0, 29, 73, 108, 132, 174, 236, 284, 318, 348, 391, 426, 452, 471, 500, 524, 543}, + {0, 20, 51, 76, 93, 123, 166, 200, 225, 247, 279, 305, 326, 342, 365, 385, 401}, + {0, 742, 845, 850, 851, 959, 997, 1001, 1002, 1009, 1014, 1016, 1017, 1019, 1020, 1021, 1022}, + {0, 42, 94, 121, 137, 186, 244, 280, 303, 330, 366, 392, 410, 427, 451, 470, 484}, + {0, 13, 33, 51, 66, 85, 114, 140, 161, 178, 203, 225, 243, 256, 275, 292, 307}, + {0, 501, 670, 689, 693, 848, 936, 952, 956, 975, 991, 997, 999, 1004, 1008, 1010, 1011}, + {0, 445, 581, 603, 609, 767, 865, 888, 895, 926, 954, 964, 968, 977, 986, 991, 993}, + {0, 285, 442, 479, 489, 650, 779, 818, 830, 870, 912, 930, 937, 949, 963, 971, 975}, + {0, 349, 528, 561, 569, 731, 852, 883, 892, 923, 953, 965, 970, 978, 987, 992, 994}, + {0, 199, 355, 402, 417, 563, 700, 750, 767, 811, 860, 884, 894, 909, 926, 936, 942}, + {0, 141, 275, 325, 343, 471, 606, 664, 686, 734, 791, 822, 836, 854, 877, 891, 899}, + {0, 243, 437, 493, 510, 649, 775, 820, 836, 869, 905, 923, 931, 941, 953, 960, 964}, + {0, 91, 197, 248, 271, 370, 487, 550, 580, 625, 684, 721, 741, 761, 788, 807, 819}, + {0, 107, 201, 242, 262, 354, 451, 503, 531, 573, 626, 660, 680, 701, 730, 751, 765}, + {0, 168, 339, 407, 432, 553, 676, 731, 755, 789, 830, 854, 866, 879, 895, 906, 912}, + {0, 67, 147, 191, 214, 290, 384, 441, 472, 513, 567, 604, 627, 648, 678, 700, 715}, + {0, 46, 109, 148, 171, 229, 307, 359, 391, 427, 476, 513, 537, 558, 588, 612, 629}, + {0, 848, 918, 920, 921, 996, 1012, 1013, 1014, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023}, + {0, 36, 88, 123, 145, 193, 260, 308, 340, 372, 417, 452, 476, 496, 525, 548, 565}, + {0, 24, 61, 90, 110, 145, 196, 237, 266, 292, 330, 361, 385, 403, 430, 453, 471}, + {0, 85, 182, 230, 253, 344, 454, 515, 545, 590, 648, 685, 706, 727, 756, 776, 789}, + {0, 22, 55, 82, 102, 135, 183, 222, 252, 278, 315, 345, 368, 385, 410, 431, 448}, + {0, 1, 2, 56, 89, 90, 91, 140, 172, 221, 268, 303, 328, 358, 388, 412, 430}, + {0, 45, 109, 152, 177, 239, 320, 376, 411, 448, 499, 537, 563, 585, 616, 640, 658}, + {0, 247, 395, 433, 445, 599, 729, 771, 785, 829, 875, 896, 905, 920, 937, 946, 951}, + {0, 231, 367, 408, 423, 557, 676, 723, 742, 786, 835, 860, 872, 889, 909, 921, 928}}; + +RAM_ALIGN const UWord16 ari_spec_freq[64][17] = { + {1, 1, 175, 48, 1, 1, 109, 36, 171, 109, 47, 20, 49, 36, 20, 10, 190}, + {18, 26, 17, 10, 27, 37, 24, 16, 22, 32, 22, 14, 17, 26, 20, 13, 683}, + {71, 92, 49, 25, 81, 102, 61, 33, 42, 57, 39, 23, 22, 30, 22, 15, 260}, + {160, 130, 46, 18, 121, 123, 55, 24, 45, 55, 31, 15, 19, 24, 15, 9, 134}, + {71, 73, 33, 18, 71, 76, 43, 26, 34, 44, 30, 20, 20, 27, 21, 15, 402}, + {48, 60, 32, 19, 58, 68, 42, 27, 31, 42, 30, 21, 19, 27, 21, 16, 463}, + {138, 109, 43, 18, 111, 112, 53, 25, 46, 55, 32, 17, 21, 27, 18, 11, 188}, + {16, 24, 22, 17, 24, 36, 31, 25, 20, 30, 25, 20, 15, 22, 19, 16, 662}, + {579, 150, 12, 2, 154, 73, 10, 2, 14, 11, 3, 1, 3, 3, 1, 1, 5}, + {398, 184, 25, 5, 176, 114, 23, 6, 25, 23, 8, 3, 6, 6, 3, 2, 17}, + {13, 21, 18, 11, 20, 29, 22, 15, 14, 20, 16, 12, 10, 14, 12, 10, 767}, + {281, 183, 37, 9, 171, 139, 37, 10, 35, 36, 15, 6, 9, 10, 6, 3, 37}, + {198, 164, 46, 13, 154, 147, 51, 16, 43, 49, 24, 10, 13, 16, 10, 5, 65}, + {1, 1, 93, 44, 1, 1, 72, 38, 86, 70, 43, 25, 40, 36, 25, 16, 432}, + {133, 141, 64, 28, 117, 122, 59, 27, 39, 48, 29, 15, 15, 20, 13, 8, 146}, + {128, 125, 49, 18, 123, 134, 59, 23, 49, 59, 32, 15, 19, 24, 15, 9, 143}, + {1, 1, 23, 17, 1, 1, 23, 18, 20, 21, 18, 15, 15, 17, 14, 12, 807}, + {70, 96, 63, 38, 89, 112, 65, 36, 37, 47, 32, 20, 17, 23, 17, 12, 250}, + {55, 75, 45, 25, 68, 90, 58, 33, 39, 54, 39, 25, 22, 31, 24, 16, 325}, + {1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 993}, + {34, 51, 38, 24, 49, 69, 52, 35, 34, 47, 37, 27, 21, 31, 25, 19, 431}, + {30, 43, 32, 22, 43, 59, 45, 31, 30, 42, 34, 25, 19, 28, 23, 18, 500}, + {9, 15, 14, 13, 14, 22, 21, 18, 13, 20, 18, 16, 11, 17, 15, 14, 774}, + {30, 44, 31, 20, 41, 58, 42, 28, 28, 39, 30, 22, 18, 26, 21, 16, 530}, + {15, 23, 20, 15, 22, 33, 28, 22, 18, 26, 23, 18, 13, 20, 18, 15, 695}, + {11, 17, 16, 13, 17, 26, 23, 19, 15, 22, 20, 17, 12, 18, 16, 14, 748}, + {448, 171, 20, 4, 178, 105, 18, 4, 23, 20, 7, 2, 5, 5, 2, 1, 11}, + {332, 188, 29, 6, 186, 133, 29, 7, 30, 30, 11, 4, 6, 7, 4, 2, 20}, + {8, 13, 13, 11, 13, 20, 18, 16, 12, 17, 16, 13, 10, 14, 13, 12, 805}, + {239, 176, 42, 11, 163, 145, 44, 13, 39, 42, 19, 7, 11, 13, 7, 4, 49}, + {165, 145, 49, 16, 138, 139, 55, 20, 47, 54, 28, 12, 16, 20, 12, 7, 101}, + {3, 5, 5, 5, 5, 7, 7, 7, 4, 7, 7, 6, 4, 6, 6, 6, 934}, + {115, 122, 52, 22, 111, 125, 61, 27, 45, 57, 34, 17, 19, 25, 17, 10, 165}, + {107, 114, 51, 21, 106, 122, 61, 28, 46, 58, 35, 18, 20, 26, 18, 11, 182}, + {6, 10, 10, 9, 10, 15, 15, 14, 9, 14, 13, 12, 8, 12, 11, 10, 846}, + {72, 88, 50, 26, 84, 102, 60, 32, 41, 53, 36, 21, 20, 27, 20, 13, 279}, + {45, 63, 45, 30, 61, 83, 58, 36, 34, 47, 34, 23, 19, 27, 21, 15, 383}, + {1, 1, 7, 7, 1, 1, 8, 8, 6, 8, 7, 7, 6, 7, 7, 6, 936}, + {29, 44, 35, 24, 42, 62, 48, 34, 30, 43, 35, 26, 19, 29, 24, 19, 481}, + {20, 31, 25, 17, 30, 43, 34, 25, 22, 32, 26, 21, 16, 23, 20, 16, 623}, + {742, 103, 5, 1, 108, 38, 4, 1, 7, 5, 2, 1, 2, 1, 1, 1, 2}, + {42, 52, 27, 16, 49, 58, 36, 23, 27, 36, 26, 18, 17, 24, 19, 14, 540}, + {13, 20, 18, 15, 19, 29, 26, 21, 17, 25, 22, 18, 13, 19, 17, 15, 717}, + {501, 169, 19, 4, 155, 88, 16, 4, 19, 16, 6, 2, 5, 4, 2, 1, 13}, + {445, 136, 22, 6, 158, 98, 23, 7, 31, 28, 10, 4, 9, 9, 5, 2, 31}, + {285, 157, 37, 10, 161, 129, 39, 12, 40, 42, 18, 7, 12, 14, 8, 4, 49}, + {349, 179, 33, 8, 162, 121, 31, 9, 31, 30, 12, 5, 8, 9, 5, 2, 30}, + {199, 156, 47, 15, 146, 137, 50, 17, 44, 49, 24, 10, 15, 17, 10, 6, 82}, + {141, 134, 50, 18, 128, 135, 58, 22, 48, 57, 31, 14, 18, 23, 14, 8, 125}, + {243, 194, 56, 17, 139, 126, 45, 16, 33, 36, 18, 8, 10, 12, 7, 4, 60}, + {91, 106, 51, 23, 99, 117, 63, 30, 45, 59, 37, 20, 20, 27, 19, 12, 205}, + {107, 94, 41, 20, 92, 97, 52, 28, 42, 53, 34, 20, 21, 29, 21, 14, 259}, + {168, 171, 68, 25, 121, 123, 55, 24, 34, 41, 24, 12, 13, 16, 11, 6, 112}, + {67, 80, 44, 23, 76, 94, 57, 31, 41, 54, 37, 23, 21, 30, 22, 15, 309}, + {46, 63, 39, 23, 58, 78, 52, 32, 36, 49, 37, 24, 21, 30, 24, 17, 395}, + {848, 70, 2, 1, 75, 16, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1}, + {36, 52, 35, 22, 48, 67, 48, 32, 32, 45, 35, 24, 20, 29, 23, 17, 459}, + {24, 37, 29, 20, 35, 51, 41, 29, 26, 38, 31, 24, 18, 27, 23, 18, 553}, + {85, 97, 48, 23, 91, 110, 61, 30, 45, 58, 37, 21, 21, 29, 20, 13, 235}, + {22, 33, 27, 20, 33, 48, 39, 30, 26, 37, 30, 23, 17, 25, 21, 17, 576}, + {1, 1, 54, 33, 1, 1, 49, 32, 49, 47, 35, 25, 30, 30, 24, 18, 594}, + {45, 64, 43, 25, 62, 81, 56, 35, 37, 51, 38, 26, 22, 31, 24, 18, 366}, + {247, 148, 38, 12, 154, 130, 42, 14, 44, 46, 21, 9, 15, 17, 9, 5, 73}, + {231, 136, 41, 15, 134, 119, 47, 19, 44, 49, 25, 12, 17, 20, 12, 7, 96}}; + +RAM_ALIGN const UWord16 ari_spec_bits[64][17] = { + {20480, 20480, 5220, 9042, 20480, 20480, 6619, 9892, 5289, 6619, 9105, 11629, 8982, 9892, 11629, 13677, 4977}, + {11940, 10854, 12109, 13677, 10742, 9812, 11090, 12288, 11348, 10240, 11348, 12683, 12109, 10854, 11629, 12902, + 1197}, + {7886, 7120, 8982, 10970, 7496, 6815, 8334, 10150, 9437, 8535, 9656, 11216, 11348, 10431, 11348, 12479, 4051}, + {5485, 6099, 9168, 11940, 6311, 6262, 8640, 11090, 9233, 8640, 10334, 12479, 11781, 11090, 12479, 13988, 6009}, + {7886, 7804, 10150, 11940, 7886, 7685, 9368, 10854, 10061, 9300, 10431, 11629, 11629, 10742, 11485, 12479, 2763}, + {9042, 8383, 10240, 11781, 8483, 8013, 9437, 10742, 10334, 9437, 10431, 11485, 11781, 10742, 11485, 12288, 2346}, + {5922, 6619, 9368, 11940, 6566, 6539, 8750, 10970, 9168, 8640, 10240, 12109, 11485, 10742, 11940, 13396, 5009}, + {12288, 11090, 11348, 12109, 11090, 9892, 10334, 10970, 11629, 10431, 10970, 11629, 12479, 11348, 11781, 12288, + 1289}, + {1685, 5676, 13138, 18432, 5598, 7804, 13677, 18432, 12683, 13396, 17234, 20480, 17234, 17234, 20480, 20480, 15725}, + {2793, 5072, 10970, 15725, 5204, 6487, 11216, 15186, 10970, 11216, 14336, 17234, 15186, 15186, 17234, 18432, 12109}, + {12902, 11485, 11940, 13396, 11629, 10531, 11348, 12479, 12683, 11629, 12288, 13138, 13677, 12683, 13138, 13677, + 854}, + {3821, 5088, 9812, 13988, 5289, 5901, 9812, 13677, 9976, 9892, 12479, 15186, 13988, 13677, 15186, 17234, 9812}, + {4856, 5412, 9168, 12902, 5598, 5736, 8863, 12288, 9368, 8982, 11090, 13677, 12902, 12288, 13677, 15725, 8147}, + {20480, 20480, 7088, 9300, 20480, 20480, 7844, 9733, 7320, 7928, 9368, 10970, 9581, 9892, 10970, 12288, 2550}, + {6031, 5859, 8192, 10635, 6410, 6286, 8433, 10742, 9656, 9042, 10531, 12479, 12479, 11629, 12902, 14336, 5756}, + {6144, 6215, 8982, 11940, 6262, 6009, 8433, 11216, 8982, 8433, 10240, 12479, 11781, 11090, 12479, 13988, 5817}, + {20480, 20480, 11216, 12109, 20480, 20480, 11216, 11940, 11629, 11485, 11940, 12479, 12479, 12109, 12683, 13138, + 704}, + {7928, 6994, 8239, 9733, 7218, 6539, 8147, 9892, 9812, 9105, 10240, 11629, 12109, 11216, 12109, 13138, 4167}, + {8640, 7724, 9233, 10970, 8013, 7185, 8483, 10150, 9656, 8694, 9656, 10970, 11348, 10334, 11090, 12288, 3391}, + {20480, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 91}, + {10061, 8863, 9733, 11090, 8982, 7970, 8806, 9976, 10061, 9105, 9812, 10742, 11485, 10334, 10970, 11781, 2557}, + {10431, 9368, 10240, 11348, 9368, 8433, 9233, 10334, 10431, 9437, 10061, 10970, 11781, 10635, 11216, 11940, 2119}, + {13988, 12479, 12683, 12902, 12683, 11348, 11485, 11940, 12902, 11629, 11940, 12288, 13396, 12109, 12479, 12683, + 828}, + {10431, 9300, 10334, 11629, 9508, 8483, 9437, 10635, 10635, 9656, 10431, 11348, 11940, 10854, 11485, 12288, 1946}, + {12479, 11216, 11629, 12479, 11348, 10150, 10635, 11348, 11940, 10854, 11216, 11940, 12902, 11629, 11940, 12479, + 1146}, + {13396, 12109, 12288, 12902, 12109, 10854, 11216, 11781, 12479, 11348, 11629, 12109, 13138, 11940, 12288, 12683, + 928}, + {2443, 5289, 11629, 16384, 5170, 6730, 11940, 16384, 11216, 11629, 14731, 18432, 15725, 15725, 18432, 20480, 13396}, + {3328, 5009, 10531, 15186, 5040, 6031, 10531, 14731, 10431, 10431, 13396, 16384, 15186, 14731, 16384, 18432, 11629}, + {14336, 12902, 12902, 13396, 12902, 11629, 11940, 12288, 13138, 12109, 12288, 12902, 13677, 12683, 12902, 13138, + 711}, + {4300, 5204, 9437, 13396, 5430, 5776, 9300, 12902, 9656, 9437, 11781, 14731, 13396, 12902, 14731, 16384, 8982}, + {5394, 5776, 8982, 12288, 5922, 5901, 8640, 11629, 9105, 8694, 10635, 13138, 12288, 11629, 13138, 14731, 6844}, + {17234, 15725, 15725, 15725, 15725, 14731, 14731, 14731, 16384, 14731, 14731, 15186, 16384, 15186, 15186, 15186, + 272}, + {6461, 6286, 8806, 11348, 6566, 6215, 8334, 10742, 9233, 8535, 10061, 12109, 11781, 10970, 12109, 13677, 5394}, + {6674, 6487, 8863, 11485, 6702, 6286, 8334, 10635, 9168, 8483, 9976, 11940, 11629, 10854, 11940, 13396, 5105}, + {15186, 13677, 13677, 13988, 13677, 12479, 12479, 12683, 13988, 12683, 12902, 13138, 14336, 13138, 13396, 13677, + 565}, + {7844, 7252, 8922, 10854, 7389, 6815, 8383, 10240, 9508, 8750, 9892, 11485, 11629, 10742, 11629, 12902, 3842}, + {9233, 8239, 9233, 10431, 8334, 7424, 8483, 9892, 10061, 9105, 10061, 11216, 11781, 10742, 11485, 12479, 2906}, + {20480, 20480, 14731, 14731, 20480, 20480, 14336, 14336, 15186, 14336, 14731, 14731, 15186, 14731, 14731, 15186, + 266}, + {10531, 9300, 9976, 11090, 9437, 8286, 9042, 10061, 10431, 9368, 9976, 10854, 11781, 10531, 11090, 11781, 2233}, + {11629, 10334, 10970, 12109, 10431, 9368, 10061, 10970, 11348, 10240, 10854, 11485, 12288, 11216, 11629, 12288, + 1469}, + {952, 6787, 15725, 20480, 6646, 9733, 16384, 20480, 14731, 15725, 18432, 20480, 18432, 20480, 20480, 20480, 18432}, + {9437, 8806, 10742, 12288, 8982, 8483, 9892, 11216, 10742, 9892, 10854, 11940, 12109, 11090, 11781, 12683, 1891}, + {12902, 11629, 11940, 12479, 11781, 10531, 10854, 11485, 12109, 10970, 11348, 11940, 12902, 11781, 12109, 12479, + 1054}, + {2113, 5323, 11781, 16384, 5579, 7252, 12288, 16384, 11781, 12288, 15186, 18432, 15725, 16384, 18432, 20480, 12902}, + {2463, 5965, 11348, 15186, 5522, 6934, 11216, 14731, 10334, 10635, 13677, 16384, 13988, 13988, 15725, 18432, 10334}, + {3779, 5541, 9812, 13677, 5467, 6122, 9656, 13138, 9581, 9437, 11940, 14731, 13138, 12683, 14336, 16384, 8982}, + {3181, 5154, 10150, 14336, 5448, 6311, 10334, 13988, 10334, 10431, 13138, 15725, 14336, 13988, 15725, 18432, 10431}, + {4841, 5560, 9105, 12479, 5756, 5944, 8922, 12109, 9300, 8982, 11090, 13677, 12479, 12109, 13677, 15186, 7460}, + {5859, 6009, 8922, 11940, 6144, 5987, 8483, 11348, 9042, 8535, 10334, 12683, 11940, 11216, 12683, 14336, 6215}, + {4250, 4916, 8587, 12109, 5901, 6191, 9233, 12288, 10150, 9892, 11940, 14336, 13677, 13138, 14731, 16384, 8383}, + {7153, 6702, 8863, 11216, 6904, 6410, 8239, 10431, 9233, 8433, 9812, 11629, 11629, 10742, 11781, 13138, 4753}, + {6674, 7057, 9508, 11629, 7120, 6964, 8806, 10635, 9437, 8750, 10061, 11629, 11485, 10531, 11485, 12683, 4062}, + {5341, 5289, 8013, 10970, 6311, 6262, 8640, 11090, 10061, 9508, 11090, 13138, 12902, 12288, 13396, 15186, 6539}, + {8057, 7533, 9300, 11216, 7685, 7057, 8535, 10334, 9508, 8694, 9812, 11216, 11485, 10431, 11348, 12479, 3541}, + {9168, 8239, 9656, 11216, 8483, 7608, 8806, 10240, 9892, 8982, 9812, 11090, 11485, 10431, 11090, 12109, 2815}, + {558, 7928, 18432, 20480, 7724, 12288, 20480, 20480, 18432, 20480, 20480, 20480, 20480, 20480, 20480, 20480, 20480}, + {9892, 8806, 9976, 11348, 9042, 8057, 9042, 10240, 10240, 9233, 9976, 11090, 11629, 10531, 11216, 12109, 2371}, + {11090, 9812, 10531, 11629, 9976, 8863, 9508, 10531, 10854, 9733, 10334, 11090, 11940, 10742, 11216, 11940, 1821}, + {7354, 6964, 9042, 11216, 7153, 6592, 8334, 10431, 9233, 8483, 9812, 11485, 11485, 10531, 11629, 12902, 4349}, + {11348, 10150, 10742, 11629, 10150, 9042, 9656, 10431, 10854, 9812, 10431, 11216, 12109, 10970, 11485, 12109, 1700}, + {20480, 20480, 8694, 10150, 20480, 20480, 8982, 10240, 8982, 9105, 9976, 10970, 10431, 10431, 11090, 11940, 1610}, + {9233, 8192, 9368, 10970, 8286, 7496, 8587, 9976, 9812, 8863, 9733, 10854, 11348, 10334, 11090, 11940, 3040}, + {4202, 5716, 9733, 13138, 5598, 6099, 9437, 12683, 9300, 9168, 11485, 13988, 12479, 12109, 13988, 15725, 7804}, + {4400, 5965, 9508, 12479, 6009, 6360, 9105, 11781, 9300, 8982, 10970, 13138, 12109, 11629, 13138, 14731, 6994}}; + +RAM_ALIGN const Word32 tnsAcfWindow_lc3plus[MAXLAG] = {0x7FBF61E2, 0x7EFE4B00, 0x7DBF01E8, 0x7C0544D0, + 0x79D636E9, 0x773846E0, 0x74330F61, 0x70CF3251}; +RAM_ALIGN const Word16 tnsQuantPts[TNS_COEF_RES] = {-32628, -31517, -29333, -26149, -22076, -17250, -11837, -6021, 0, + 6021, 11837, 17250, 22076, 26149, 29333, 31517, 32628}; +RAM_ALIGN const Word16 tnsQuantThr[TNS_COEF_RES - 1] = {-32210, -30555, -27860, -24216, -19747, -14606, -8967, -3023, + 3023, 8967, 14606, 19747, 24216, 27860, 30555, 32210}; + +RAM_ALIGN const Word16 ac_tns_order_bits[2][MAXLAG] = {{17234, 13988, 11216, 8694, 6566, 4977, 3961, 3040}, + {12683, 9437, 6874, 5541, 5121, 5170, 5359, 5056}}; +RAM_ALIGN const Word16 ac_tns_order_freq[2][MAXLAG] = {{3, 9, 23, 54, 111, 190, 268, 366}, + {14, 42, 100, 157, 181, 178, 167, 185}}; +RAM_ALIGN const Word16 ac_tns_order_cumfreq[2][MAXLAG] = {{0, 3, 12, 35, 89, 200, 390, 658}, + {0, 14, 56, 156, 313, 494, 672, 839}}; +RAM_ALIGN const Word16 ac_tns_coef_bits[MAXLAG][TNS_COEF_RES] = { + {20480, 15725, 12479, 10334, 8694, 7320, 6964, 6335, 5504, 5637, 6566, 6758, 8433, 11348, 15186, 20480, 20480}, + {20480, 20480, 20480, 20480, 12902, 9368, 7057, 5901, 5254, 5485, 5598, 6076, 7608, 10742, 15186, 20480, 20480}, + {20480, 20480, 20480, 20480, 13988, 9368, 6702, 4841, 4585, 4682, 5859, 7764, 12109, 20480, 20480, 20480, 20480}, + {20480, 20480, 20480, 20480, 18432, 13396, 8982, 4767, 3779, 3658, 6335, 9656, 13988, 20480, 20480, 20480, 20480}, + {20480, 20480, 20480, 20480, 20480, 14731, 9437, 4275, 3249, 3493, 8483, 13988, 17234, 20480, 20480, 20480, 20480}, + {20480, 20480, 20480, 20480, 20480, 20480, 12902, 4753, 3040, 2953, 9105, 15725, 20480, 20480, 20480, 20480, 20480}, + {20480, 20480, 20480, 20480, 20480, 20480, 12902, 3821, 3346, 3000, 12109, 20480, 20480, 20480, 20480, 20480, + 20480}, + {20480, 20480, 20480, 20480, 20480, 20480, 15725, 3658, 20480, 1201, 10854, 18432, 20480, 20480, 20480, 20480, + 20480}}; +RAM_ALIGN const Word16 ac_tns_coef_freq[MAXLAG][TNS_COEF_RES] = { + {1, 5, 15, 31, 54, 86, 97, 120, 159, 152, 111, 104, 59, 22, 6, 1, 1}, + {1, 1, 1, 1, 13, 43, 94, 139, 173, 160, 154, 131, 78, 27, 6, 1, 1}, + {1, 1, 1, 1, 9, 43, 106, 199, 217, 210, 141, 74, 17, 1, 1, 1, 1}, + {1, 1, 1, 1, 2, 11, 49, 204, 285, 297, 120, 39, 9, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 7, 42, 241, 341, 314, 58, 9, 3, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 13, 205, 366, 377, 47, 5, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 13, 281, 330, 371, 17, 1, 1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1, 1, 5, 297, 1, 682, 26, 2, 1, 1, 1, 1, 1}}; +RAM_ALIGN const Word16 ac_tns_coef_cumfreq[MAXLAG][TNS_COEF_RES] = { + {0, 1, 6, 21, 52, 106, 192, 289, 409, 568, 720, 831, 935, 994, 1016, 1022, 1023}, + {0, 1, 2, 3, 4, 17, 60, 154, 293, 466, 626, 780, 911, 989, 1016, 1022, 1023}, + {0, 1, 2, 3, 4, 13, 56, 162, 361, 578, 788, 929, 1003, 1020, 1021, 1022, 1023}, + {0, 1, 2, 3, 4, 6, 17, 66, 270, 555, 852, 972, 1011, 1020, 1021, 1022, 1023}, + {0, 1, 2, 3, 4, 5, 12, 54, 295, 636, 950, 1008, 1017, 1020, 1021, 1022, 1023}, + {0, 1, 2, 3, 4, 5, 6, 19, 224, 590, 967, 1014, 1019, 1020, 1021, 1022, 1023}, + {0, 1, 2, 3, 4, 5, 6, 19, 300, 630, 1001, 1018, 1019, 1020, 1021, 1022, 1023}, + {0, 1, 2, 3, 4, 5, 6, 11, 308, 309, 991, 1017, 1019, 1020, 1021, 1022, 1023}}; + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_8000[64] = { + 0x4000, 0x435c, 0x46e5, 0x4a9e, 0x4e89, 0x52a9, 0x5700, 0x5b91, 0x6060, 0x656f, 0x6ac2, 0x705d, 0x7643, + 0x7c79, 0x4181, 0x44f1, 0x4890, 0x4c5f, 0x5061, 0x549a, 0x590b, 0x5db7, 0x62a3, 0x67d1, 0x6d44, 0x7301, + 0x790a, 0x7f65, 0x430b, 0x4690, 0x4a44, 0x4e2a, 0x5245, 0x5696, 0x5b22, 0x5feb, 0x64f4, 0x6a41, 0x6fd5, + 0x75b4, 0x7be2, 0x4131, 0x449e, 0x4838, 0x4c02, 0x5000, 0x5433, 0x589f, 0x5d46, 0x622c, 0x6753, 0x6cc0, + 0x7275, 0x7878, 0x7ecb, 0x42b9, 0x463a, 0x49ea, 0x4dcb, 0x51e1, 0x562d, 0x5ab4, 0x5f77, 0x647a}; + +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_e_8000[64] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05}; +#else +#define lpc_warp_pre_emphasis_64_8000 NULL +#define lpc_warp_pre_emphasis_64_e_8000 NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_16000[64] = { + 0x4000, 0x445a, 0x4900, 0x4df7, 0x5344, 0x58ed, 0x5efa, 0x656f, 0x6c55, 0x73b2, 0x7b91, 0x41fc, 0x4678, + 0x4b43, 0x5061, 0x55d9, 0x5baf, 0x61eb, 0x6894, 0x6fb0, 0x7748, 0x7f65, 0x4407, 0x48a8, 0x4d98, 0x52df, + 0x5882, 0x5e87, 0x64f4, 0x6bd1, 0x7326, 0x7afb, 0x41ac, 0x4623, 0x4ae8, 0x5000, 0x5571, 0x5b40, 0x6174, + 0x6815, 0x6f29, 0x76b8, 0x7ecb, 0x43b5, 0x4850, 0x4d3a, 0x527b, 0x5817, 0x5e14, 0x647a, 0x6b4f, 0x729b, + 0x7a66, 0x415c, 0x45ce, 0x4a8d, 0x4f9f, 0x5509, 0x5ad1, 0x60fe, 0x6797, 0x6ea2, 0x7628, 0x7e31}; + +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_e_16000[64] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06}; +#else +#define lpc_warp_pre_emphasis_64_16000 NULL +#define lpc_warp_pre_emphasis_64_e_16000 NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_24000[64] = { + 0x4000, 0x455c, 0x4b2a, 0x5176, 0x5848, 0x5fac, 0x67af, 0x705d, 0x79c5, 0x41fc, 0x4782, 0x4d7f, 0x53fc, + 0x5b04, 0x62a3, 0x6ae5, 0x73d9, 0x7d8c, 0x4407, 0x49b9, 0x4fe6, 0x5696, 0x5dd6, 0x65b2, 0x6e35, 0x7770, + 0x40b8, 0x4623, 0x4c02, 0x5260, 0x5945, 0x60bf, 0x68d8, 0x71a0, 0x7b23, 0x42b9, 0x4850, 0x4e5e, 0x54ed, + 0x5c0a, 0x63be, 0x6c18, 0x7525, 0x7ef4, 0x44cb, 0x4a8d, 0x50cb, 0x578f, 0x5ee4, 0x66d6, 0x6f72, 0x78c7, + 0x4172, 0x46ed, 0x4cdd, 0x534c, 0x5a46, 0x61d5, 0x6a06, 0x72e6, 0x7c85, 0x4379, 0x491f, 0x4f3f}; + +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_e_24000[64] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08}; +#else +#define lpc_warp_pre_emphasis_64_24000 NULL +#define lpc_warp_pre_emphasis_64_e_24000 NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_32000[64] = { + 0x4000, 0x4661, 0x4d65, 0x551d, 0x5d99, 0x66ed, 0x7130, 0x7c79, 0x4471, 0x4b43, 0x52c4, 0x5b04, 0x6417, + 0x6e11, 0x790a, 0x428e, 0x4930, 0x507c, 0x5882, 0x6154, 0x6b08, 0x75b4, 0x40b8, 0x472b, 0x4e44, 0x5611, + 0x5ea6, 0x6815, 0x7275, 0x7dde, 0x4535, 0x4c1b, 0x53b2, 0x5c0a, 0x6536, 0x6f4d, 0x7a66, 0x434d, 0x4a02, + 0x5163, 0x5980, 0x626c, 0x6c3c, 0x7706, 0x4172, 0x47f8, 0x4f25, 0x5708, 0x5fb5, 0x6940, 0x73be, 0x7f48, + 0x45fc, 0x4cf6, 0x54a2, 0x5d12, 0x6659, 0x708d, 0x7bc6, 0x440e, 0x4ad7, 0x524d, 0x5a81, 0x6387}; + +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_e_32000[64] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09}; +#else +#define lpc_warp_pre_emphasis_64_32000 NULL +#define lpc_warp_pre_emphasis_64_e_32000 NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_48000[64] = { + 0x4000, 0x476b, 0x4fb1, 0x58ed, 0x633c, 0x6ebc, 0x7b91, 0x44f1, 0x4cee, 0x55d9, 0x5fcb, 0x6ae5, 0x7748, + 0x428e, 0x4a44, 0x52df, 0x5c7a, 0x6731, 0x7326, 0x403f, 0x47b1, 0x5000, 0x5945, 0x639e, 0x6f29, 0x7c0b, + 0x4535, 0x4d3a, 0x562d, 0x602a, 0x6b4f, 0x77be, 0x42cf, 0x4a8d, 0x5331, 0x5cd5, 0x6797, 0x7398, 0x407f, + 0x47f8, 0x504f, 0x599d, 0x6400, 0x6f97, 0x7c85, 0x457a, 0x4d87, 0x5683, 0x6089, 0x6bb9, 0x7834, 0x4311, + 0x4ad7, 0x5383, 0x5d31, 0x67fd, 0x740a, 0x40be, 0x483f, 0x509e, 0x59f6, 0x6463, 0x7005, 0x7d00}; + +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_e_48000[64] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}; +#else +#define lpc_warp_pre_emphasis_64_48000 NULL +#define lpc_warp_pre_emphasis_64_e_48000 NULL +#endif + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_96000[64] = { + 0x4000, 0x4878, 0x520f, 0x5cea, 0x6936, 0x7721, 0x4372, 0x4c5f, 0x567a, 0x61eb, 0x6ee0, 0x7d8c, 0x4714, + 0x507c, 0x5b22, 0x6731, 0x74d8, 0x4227, 0x4ae8, 0x54d1, 0x600a, 0x6cc0, 0x7b23, 0x45b7, 0x4ef1, 0x5963, + 0x6536, 0x729b, 0x40e2, 0x4978, 0x5331, 0x5e33, 0x6aaa, 0x78c7, 0x4461, 0x4d6d, 0x57ac, 0x6346, 0x7068, + 0x7f48, 0x4810, 0x5199, 0x5c64, 0x689e, 0x7676, 0x4311, 0x4bf1, 0x55fd, 0x615e, 0x6e40, 0x7cd7, 0x46ae, + 0x5008, 0x5a9f, 0x669d, 0x7430, 0x41c8, 0x4a7c, 0x5457, 0x5f80, 0x6c23, 0x7a72, 0x4553, 0x4e7f}; + +RAM_ALIGN const Word16 lpc_warp_pre_emphasis_64_e_96000[64] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c}; +#else +# define lpc_warp_pre_emphasis_64_96000 NULL +# define lpc_warp_pre_emphasis_64_e_96000 NULL +#endif + +RAM_ALIGN const Word16 *const lpc_pre_emphasis[NUM_SAMP_FREQ] = {lpc_warp_pre_emphasis_64_8000, + lpc_warp_pre_emphasis_64_16000, + lpc_warp_pre_emphasis_64_24000, + lpc_warp_pre_emphasis_64_32000, + lpc_warp_pre_emphasis_64_48000, + lpc_warp_pre_emphasis_64_96000 +}; + +RAM_ALIGN const Word16 *const lpc_pre_emphasis_e[NUM_SAMP_FREQ] = {lpc_warp_pre_emphasis_64_e_8000, + lpc_warp_pre_emphasis_64_e_16000, + lpc_warp_pre_emphasis_64_e_24000, + lpc_warp_pre_emphasis_64_e_32000, + lpc_warp_pre_emphasis_64_e_48000, + lpc_warp_pre_emphasis_64_e_96000 +}; + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_20_8000[20] = {0x4be4, 0x5b79, 0x7a43, 0x53bf, 0x7106, 0x4a1f, 0x5e46, + 0x7477, 0x4613, 0x5260, 0x5ed4, 0x6b21, 0x76f9, 0x4109, + 0x4612, 0x4a79, 0x4e22, 0x50f6, 0x52e2, 0x53dc}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_20_e_8000[20] = { + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_8000[40] = { + 0x4a6c, 0x4e55, 0x5622, 0x61c5, 0x712d, 0x4220, 0x4d71, 0x5a77, 0x691e, 0x794e, 0x4577, 0x4ef1, 0x5906, 0x63a6, + 0x6ec1, 0x7a44, 0x430f, 0x491f, 0x4f46, 0x557c, 0x5bb8, 0x61ee, 0x6815, 0x6e25, 0x7412, 0x79d4, 0x7f61, 0x4259, + 0x44de, 0x473c, 0x4970, 0x4b76, 0x4d4b, 0x4eec, 0x5056, 0x5187, 0x527e, 0x5338, 0x53b5, 0x53f3}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_e_8000[40] = { + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_8000[80] = { + 0x4a0e, 0x4b09, 0x4cfd, 0x4fec, 0x53d2, 0x58af, 0x5e81, 0x6545, 0x6cf9, 0x759a, 0x7f25, 0x44ca, 0x4a73, 0x508a, + 0x570e, 0x5dfa, 0x654e, 0x6d06, 0x751e, 0x7d94, 0x4332, 0x47c6, 0x4c83, 0x5168, 0x5673, 0x5ba2, 0x60f2, 0x6662, + 0x6bf0, 0x7199, 0x775b, 0x7d34, 0x4191, 0x4490, 0x4798, 0x4aa7, 0x4dba, 0x50d3, 0x53ee, 0x570b, 0x5a29, 0x5d46, + 0x6061, 0x637a, 0x668e, 0x699c, 0x6ca4, 0x6fa3, 0x729a, 0x7587, 0x7868, 0x7b3c, 0x7e03, 0x405e, 0x41b2, 0x42fd, + 0x4440, 0x4579, 0x46a9, 0x47cd, 0x48e7, 0x49f6, 0x4af9, 0x4bf0, 0x4cdb, 0x4db8, 0x4e89, 0x4f4c, 0x5001, 0x50a8, + 0x5140, 0x51ca, 0x5246, 0x52b2, 0x530f, 0x535d, 0x539b, 0x53ca, 0x53e9, 0x53f9}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_8000[80] = { + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +#else +#define lpc_lin_pre_emphasis_20_8000 NULL +#define lpc_lin_pre_emphasis_20_e_8000 NULL +#define lpc_lin_pre_emphasis_40_8000 NULL +#define lpc_lin_pre_emphasis_40_e_8000 NULL +#define lpc_lin_pre_emphasis_80_8000 NULL +#define lpc_lin_pre_emphasis_80_e_8000 NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_16000[40] = { + 0x516b, 0x5a81, 0x6c9d, 0x43d2, 0x55b6, 0x6bdd, 0x4313, 0x5233, 0x6336, 0x7602, 0x453d, 0x503e, 0x5bf4, 0x684b, + 0x7530, 0x4148, 0x4829, 0x4f33, 0x5658, 0x5d8f, 0x64cc, 0x6c03, 0x7328, 0x7a32, 0x408a, 0x43e1, 0x471b, 0x4a31, + 0x4d1e, 0x4fde, 0x526d, 0x54c7, 0x56e7, 0x58cb, 0x5a70, 0x5bd2, 0x5cf0, 0x5dc9, 0x5e59, 0x5ea2}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_e_16000[40] = { + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_16000[80] = { + 0x5091, 0x52d7, 0x5762, 0x5e30, 0x673f, 0x728b, 0x4008, 0x47e3, 0x50d6, 0x5adb, 0x65ef, 0x720e, 0x7f33, 0x46ac, + 0x4e3c, 0x5647, 0x5ec9, 0x67bf, 0x7126, 0x7afa, 0x429b, 0x47ec, 0x4d6d, 0x531c, 0x58f7, 0x5efb, 0x6527, 0x6b78, + 0x71eb, 0x787d, 0x7f2d, 0x42fc, 0x466d, 0x49e8, 0x4d6d, 0x50fa, 0x548d, 0x5825, 0x5bc1, 0x5f5e, 0x62fd, 0x669a, + 0x6a36, 0x6dce, 0x7161, 0x74ee, 0x7872, 0x7bee, 0x7f5f, 0x4162, 0x430e, 0x44b3, 0x4650, 0x47e4, 0x496f, 0x4af0, + 0x4c67, 0x4dd2, 0x4f33, 0x5087, 0x51ce, 0x5309, 0x5436, 0x5554, 0x5665, 0x5766, 0x5858, 0x593a, 0x5a0d, 0x5acf, + 0x5b80, 0x5c20, 0x5caf, 0x5d2d, 0x5d99, 0x5df4, 0x5e3c, 0x5e72, 0x5e97, 0x5ea9}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_16000[80] = { + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +#else +#define lpc_lin_pre_emphasis_40_16000 NULL +#define lpc_lin_pre_emphasis_40_e_16000 NULL +#define lpc_lin_pre_emphasis_80_16000 NULL +#define lpc_lin_pre_emphasis_80_e_16000 NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_24000[40] = { + 0x44f2, 0x59a3, 0x4172, 0x603b, 0x447d, 0x5db8, 0x7ba7, 0x4f0d, 0x626d, 0x77d6, 0x4793, 0x541b, 0x6171, 0x6f7f, + 0x7e2f, 0x46b5, 0x4e8b, 0x568f, 0x5eb2, 0x66ea, 0x6f28, 0x775f, 0x7f83, 0x43c3, 0x47ae, 0x4b7d, 0x4f29, 0x52ac, + 0x5602, 0x5924, 0x5c0e, 0x5ebb, 0x6127, 0x634e, 0x652d, 0x66c1, 0x6807, 0x68fd, 0x69a2, 0x69f5}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_40_e_24000[40] = { + (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_24000[60] = { + 0x4382, 0x4cb6, 0x5f17, 0x7a99, 0x4f94, 0x6656, 0x40c0, 0x5081, 0x6263, 0x7658, 0x4629, 0x5222, + 0x5f0e, 0x6ce3, 0x7b98, 0x4591, 0x4dbc, 0x5647, 0x5f2b, 0x6862, 0x71e7, 0x7bb2, 0x42de, 0x47ff, + 0x4d39, 0x5288, 0x57e8, 0x5d55, 0x62cc, 0x6849, 0x6dc8, 0x7345, 0x78bc, 0x7e29, 0x41c5, 0x446c, + 0x4709, 0x499a, 0x4c1c, 0x4e8f, 0x50f0, 0x533e, 0x5577, 0x579a, 0x59a4, 0x5b96, 0x5d6c, 0x5f27, + 0x60c4, 0x6243, 0x63a3, 0x64e2, 0x6601, 0x66fd, 0x67d6, 0x688c, 0x691e, 0x698c, 0x69d6, 0x69fb}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_e_24000[60] = { + (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_24000[80] = { + 0x4301, 0x482e, 0x5287, 0x6208, 0x76a9, 0x4832, 0x5797, 0x697e, 0x7dde, 0x4a59, 0x56f7, 0x64c5, 0x73bd, 0x41ed, + 0x4a8a, 0x53b2, 0x5d63, 0x6798, 0x724d, 0x7d7e, 0x4493, 0x4aa1, 0x50e5, 0x575e, 0x5e0a, 0x64e4, 0x6beb, 0x731d, + 0x7a75, 0x40f9, 0x44c7, 0x48a5, 0x4c91, 0x5088, 0x548a, 0x5895, 0x5ca7, 0x60bf, 0x64db, 0x68f9, 0x6d18, 0x7136, + 0x7552, 0x796a, 0x7d7c, 0x40c4, 0x42c4, 0x44c0, 0x46b6, 0x48a5, 0x4a8c, 0x4c6b, 0x4e41, 0x500e, 0x51d0, 0x5386, + 0x5531, 0x56cf, 0x5860, 0x59e4, 0x5b59, 0x5cbf, 0x5e16, 0x5f5c, 0x6092, 0x61b7, 0x62cb, 0x63cd, 0x64bc, 0x6599, + 0x6663, 0x671a, 0x67bd, 0x684c, 0x68c7, 0x692e, 0x6980, 0x69be, 0x69e8, 0x69fd}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_24000[80] = { + (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +#else +#define lpc_lin_pre_emphasis_60_24000 NULL +#define lpc_lin_pre_emphasis_60_e_24000 NULL +#define lpc_lin_pre_emphasis_40_24000 NULL +#define lpc_lin_pre_emphasis_40_e_24000 NULL +#define lpc_lin_pre_emphasis_80_24000 NULL +#define lpc_lin_pre_emphasis_80_e_24000 NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_32000[80] = { + 0x6eab, 0x4e92, 0x7d03, 0x614a, 0x47cb, 0x64a9, 0x439a, 0x57af, 0x6e8c, 0x4414, 0x523c, 0x61b9, 0x7284, 0x424c, + 0x4bf6, 0x563d, 0x611c, 0x6c8f, 0x7892, 0x4290, 0x491a, 0x4fe5, 0x56ed, 0x5e31, 0x65ac, 0x6d5d, 0x753f, 0x7d51, + 0x42c7, 0x46fa, 0x4b40, 0x4f96, 0x53fc, 0x5870, 0x5cef, 0x6178, 0x6609, 0x6aa1, 0x6f3d, 0x73dc, 0x787b, 0x7d1a, + 0x40db, 0x4327, 0x4570, 0x47b4, 0x49f4, 0x4c2d, 0x4e60, 0x508b, 0x52ae, 0x54c8, 0x56d7, 0x58dc, 0x5ad4, 0x5cc0, + 0x5e9f, 0x6070, 0x6232, 0x63e5, 0x6587, 0x6719, 0x689a, 0x6a08, 0x6b64, 0x6cad, 0x6de2, 0x6f03, 0x7010, 0x7108, + 0x71ea, 0x72b7, 0x736e, 0x740f, 0x7499, 0x750c, 0x7569, 0x75ae, 0x75dd, 0x75f4}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_32000[80] = { + (Word16)0xfff9, (Word16)0xfffa, (Word16)0xfffa, (Word16)0xfffb, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +#else +#define lpc_lin_pre_emphasis_80_32000 NULL +#define lpc_lin_pre_emphasis_80_e_32000 NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_48000[60] = { + 0x7330, 0x62e5, 0x5ab1, 0x4c35, 0x753a, 0x5425, 0x72a0, 0x4afd, 0x5f0d, 0x7571, 0x470d, 0x547b, + 0x62fa, 0x727f, 0x4180, 0x4a38, 0x5362, 0x5cf7, 0x66f0, 0x7148, 0x7bf5, 0x4379, 0x491b, 0x4edc, + 0x54b9, 0x5aae, 0x60b6, 0x66cd, 0x6cee, 0x7316, 0x7941, 0x7f69, 0x42c5, 0x45d1, 0x48d4, 0x4bcf, + 0x4ebd, 0x519e, 0x546f, 0x572e, 0x59d9, 0x5c6f, 0x5eee, 0x6153, 0x639d, 0x65cb, 0x67dc, 0x69cc, + 0x6b9c, 0x6d4a, 0x6ed4, 0x703b, 0x717c, 0x7296, 0x738a, 0x7457, 0x74fb, 0x7576, 0x75c9, 0x75f2}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_e_48000[60] = { + (Word16)0xfff9, (Word16)0xfffa, (Word16)0xfffb, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_48000[80] = { + 0x6eab, 0x4e92, 0x7d03, 0x614a, 0x47cb, 0x64a9, 0x439a, 0x57af, 0x6e8c, 0x4414, 0x523c, 0x61b9, 0x7284, 0x424c, + 0x4bf6, 0x563d, 0x611c, 0x6c8f, 0x7892, 0x4290, 0x491a, 0x4fe5, 0x56ed, 0x5e31, 0x65ac, 0x6d5d, 0x753f, 0x7d51, + 0x42c7, 0x46fa, 0x4b40, 0x4f96, 0x53fc, 0x5870, 0x5cef, 0x6178, 0x6609, 0x6aa1, 0x6f3d, 0x73dc, 0x787b, 0x7d1a, + 0x40db, 0x4327, 0x4570, 0x47b4, 0x49f4, 0x4c2d, 0x4e60, 0x508b, 0x52ae, 0x54c8, 0x56d7, 0x58dc, 0x5ad4, 0x5cc0, + 0x5e9f, 0x6070, 0x6232, 0x63e5, 0x6587, 0x6719, 0x689a, 0x6a08, 0x6b64, 0x6cad, 0x6de2, 0x6f03, 0x7010, 0x7108, + 0x71ea, 0x72b7, 0x736e, 0x740f, 0x7499, 0x750c, 0x7569, 0x75ae, 0x75dd, 0x75f4}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_48000[80] = { + (Word16)0xfff9, (Word16)0xfffa, (Word16)0xfffa, (Word16)0xfffb, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +#else +#define lpc_lin_pre_emphasis_60_48000 NULL +#define lpc_lin_pre_emphasis_60_e_48000 NULL +#define lpc_lin_pre_emphasis_80_48000 NULL +#define lpc_lin_pre_emphasis_80_e_48000 NULL +#endif + +# if defined(SUBSET_SWB) || defined(SUBSET_FB) +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_0_92[80] = { + 0x6eab, 0x4e92, 0x7d03, 0x614a, 0x47cb, 0x64a9, 0x439a, 0x57af, 0x6e8c, 0x4414, 0x523c, 0x61b9, 0x7284, 0x424c, + 0x4bf6, 0x563d, 0x611c, 0x6c8f, 0x7892, 0x4290, 0x491a, 0x4fe5, 0x56ed, 0x5e31, 0x65ac, 0x6d5d, 0x753f, 0x7d51, + 0x42c7, 0x46fa, 0x4b40, 0x4f96, 0x53fc, 0x5870, 0x5cef, 0x6178, 0x6609, 0x6aa1, 0x6f3d, 0x73dc, 0x787b, 0x7d1a, + 0x40db, 0x4327, 0x4570, 0x47b4, 0x49f4, 0x4c2d, 0x4e60, 0x508b, 0x52ae, 0x54c8, 0x56d7, 0x58dc, 0x5ad4, 0x5cc0, + 0x5e9f, 0x6070, 0x6232, 0x63e5, 0x6587, 0x6719, 0x689a, 0x6a08, 0x6b64, 0x6cad, 0x6de2, 0x6f03, 0x7010, 0x7108, + 0x71ea, 0x72b7, 0x736e, 0x740f, 0x7499, 0x750c, 0x7569, 0x75ae, 0x75dd, 0x75f4}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_80_e_0_92[80] = { + (Word16)0xfff9, (Word16)0xfffa, (Word16)0xfffa, (Word16)0xfffb, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, + (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; +# else +# define lpc_lin_pre_emphasis_80_0_92 NULL +# define lpc_lin_pre_emphasis_80_e_0_92 NULL +# endif + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis[NUM_SAMP_FREQ] = {lpc_lin_pre_emphasis_80_8000, lpc_lin_pre_emphasis_80_16000, + lpc_lin_pre_emphasis_80_24000, lpc_lin_pre_emphasis_80_32000, + lpc_lin_pre_emphasis_80_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_0_92 +#endif + }; + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_80_e_8000, lpc_lin_pre_emphasis_80_e_16000, lpc_lin_pre_emphasis_80_e_24000, + lpc_lin_pre_emphasis_80_e_32000, lpc_lin_pre_emphasis_80_e_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_e_0_92 +#endif +}; + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_5ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_40_8000, lpc_lin_pre_emphasis_80_16000, lpc_lin_pre_emphasis_40_24000, + lpc_lin_pre_emphasis_80_32000, lpc_lin_pre_emphasis_80_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_0_92 +#endif +}; + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_5ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_40_e_8000, lpc_lin_pre_emphasis_80_e_16000, lpc_lin_pre_emphasis_40_e_24000, + lpc_lin_pre_emphasis_80_e_32000, lpc_lin_pre_emphasis_80_e_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_e_0_92 +#endif +}; + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_2_5ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_20_8000, lpc_lin_pre_emphasis_40_16000, lpc_lin_pre_emphasis_60_24000, + lpc_lin_pre_emphasis_80_32000, lpc_lin_pre_emphasis_60_48000 +#ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_0_92 +#endif +}; + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_2_5ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_20_e_8000, lpc_lin_pre_emphasis_40_e_16000, lpc_lin_pre_emphasis_60_e_24000, + lpc_lin_pre_emphasis_80_e_32000, lpc_lin_pre_emphasis_60_e_48000 +# ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_e_0_92 +#endif +}; + +# ifdef ENABLE_075_DMS_MODE +# ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_0_62[60] = { + 0x4a26, 0x4be4, 0x4f5d, 0x5490, 0x5b79, 0x6414, 0x6e59, 0x7a43, 0x43e4, 0x4b6f, 0x53bf, 0x5ccc, 0x6690, 0x7106, + 0x7c25, 0x43f3, 0x4a1f, 0x5095, 0x574e, 0x5e46, 0x6578, 0x6cdf, 0x7477, 0x7c39, 0x4210, 0x4613, 0x4a24, 0x4e3e, + 0x5260, 0x5686, 0x5aae, 0x5ed4, 0x62f6, 0x6710, 0x6b21, 0x6f24, 0x7318, 0x76f9, 0x7ac4, 0x7e78, 0x4109, 0x42c7, + 0x4475, 0x4612, 0x479d, 0x4915, 0x4a79, 0x4bc8, 0x4d01, 0x4e22, 0x4f2c, 0x501e, 0x50f6, 0x51b4, 0x5259, 0x52e2, + 0x5351, 0x53a4, 0x53dc, 0x53f8}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_e_0_62[60] = { + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_0_72[60] = { + 0x50c9, 0x54d4, 0x5ce6, 0x68f9, 0x7906, 0x4681, 0x526e, 0x6043, 0x6ff6, 0x40be, 0x4a65, 0x54e8, 0x6040, 0x6c65, + 0x794f, 0x437a, 0x4aa6, 0x5226, 0x59f5, 0x620c, 0x6a68, 0x7301, 0x7bd2, 0x426a, 0x4701, 0x4baa, 0x5062, 0x5526, + 0x59f2, 0x5ec4, 0x6397, 0x6869, 0x6d35, 0x71f9, 0x76b1, 0x7b5a, 0x7ff1, 0x4239, 0x446d, 0x4694, 0x48aa, 0x4ab0, + 0x4ca4, 0x4e84, 0x504f, 0x5204, 0x53a1, 0x5526, 0x5691, 0x57e1, 0x5916, 0x5a2e, 0x5b29, 0x5c07, 0x5cc5, 0x5d65, + 0x5de6, 0x5e46, 0x5e87, 0x5ea7}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_e_0_72[60] = { + (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_0_82[60] = { + 0x4382, 0x4cb6, 0x5f17, 0x7a99, 0x4f94, 0x6656, 0x40c0, 0x5081, 0x6263, 0x7658, 0x4629, 0x5222, 0x5f0e, 0x6ce3, + 0x7b98, 0x4591, 0x4dbc, 0x5647, 0x5f2b, 0x6862, 0x71e7, 0x7bb2, 0x42de, 0x47ff, 0x4d39, 0x5288, 0x57e8, 0x5d55, + 0x62cc, 0x6849, 0x6dc8, 0x7345, 0x78bc, 0x7e29, 0x41c5, 0x446c, 0x4709, 0x499a, 0x4c1c, 0x4e8f, 0x50f0, 0x533e, + 0x5577, 0x579a, 0x59a4, 0x5b96, 0x5d6c, 0x5f27, 0x60c4, 0x6243, 0x63a3, 0x64e2, 0x6601, 0x66fd, 0x67d6, 0x688c, + 0x691e, 0x698c, 0x69d6, 0x69fb}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_e_0_82[60] = { + (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0000, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_0_92[60] = { + 0x7330, 0x62e5, 0x5ab1, 0x4c35, 0x753a, 0x5425, 0x72a0, 0x4afd, 0x5f0d, 0x7571, 0x470d, 0x547b, 0x62fa, 0x727f, + 0x4180, 0x4a38, 0x5362, 0x5cf7, 0x66f0, 0x7148, 0x7bf5, 0x4379, 0x491b, 0x4edc, 0x54b9, 0x5aae, 0x60b6, 0x66cd, + 0x6cee, 0x7316, 0x7941, 0x7f69, 0x42c5, 0x45d1, 0x48d4, 0x4bcf, 0x4ebd, 0x519e, 0x546f, 0x572e, 0x59d9, 0x5c6f, + 0x5eee, 0x6153, 0x639d, 0x65cb, 0x67dc, 0x69cc, 0x6b9c, 0x6d4a, 0x6ed4, 0x703b, 0x717c, 0x7296, 0x738a, 0x7457, + 0x74fb, 0x7576, 0x75c9, 0x75f2}; +RAM_ALIGN const Word16 lpc_lin_pre_emphasis_60_e_0_92[60] = { + (Word16)0xfff9, (Word16)0xfffa, (Word16)0xfffb, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffd, (Word16)0xfffd, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, + (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0001, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, + (Word16)0x0002, (Word16)0x0002, (Word16)0x0002, (Word16)0x0002}; + +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_7_5ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_60_0_62, lpc_lin_pre_emphasis_60_0_72, lpc_lin_pre_emphasis_60_0_82, + lpc_lin_pre_emphasis_80_0_92, lpc_lin_pre_emphasis_60_0_92 +# ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_0_92 +# endif + }; +RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_7_5ms[NUM_SAMP_FREQ] = { + lpc_lin_pre_emphasis_60_e_0_62, lpc_lin_pre_emphasis_60_e_0_72, lpc_lin_pre_emphasis_60_e_0_82, + lpc_lin_pre_emphasis_80_e_0_92, lpc_lin_pre_emphasis_60_e_0_92 +# ifdef ENABLE_HR_MODE + , lpc_lin_pre_emphasis_80_e_0_92 +# endif + }; +# endif +# endif + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_8000[16] = {0x4000, 0x673f, 0x5348, 0x432d, 0x6c5f, 0x576a, + 0x4682, 0x71bf, 0x5bc0, 0x4a02, 0x7764, 0x604d, + 0x4dae, 0x7d50, 0x6514, 0x5188}; + +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_e_8000[16] = { + (Word16)0x0001, (Word16)0x0000, (Word16)0x0000, (Word16)0x0000, (Word16)0xffff, (Word16)0xffff, + (Word16)0xffff, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffd, (Word16)0xfffd, + (Word16)0xfffd, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffc}; +#else +#define lpc_warp_dee_emphasis_16_8000 NULL +#define lpc_warp_dee_emphasis_16_e_8000 NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_16000[16] = {0x4000, 0x6119, 0x49a8, 0x6fc0, 0x54c5, 0x404e, + 0x618f, 0x4a02, 0x7048, 0x552c, 0x409c, 0x6206, + 0x4a5c, 0x70d0, 0x5594, 0x40eb}; + +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_e_16000[16] = { + (Word16)0x0001, (Word16)0x0000, (Word16)0x0000, (Word16)0xffff, (Word16)0xffff, (Word16)0xffff, + (Word16)0xfffe, (Word16)0xfffe, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffc, + (Word16)0xfffc, (Word16)0xfffb, (Word16)0xfffb, (Word16)0xfffb}; +#else +#define lpc_warp_dee_emphasis_16_16000 NULL +#define lpc_warp_dee_emphasis_16_e_16000 NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_24000[16] = {0x4000, 0x5b51, 0x4125, 0x5cf3, 0x424f, 0x5e9c, + 0x437f, 0x604d, 0x44b4, 0x6206, 0x45ee, 0x63c7, + 0x472e, 0x658f, 0x4874, 0x6760}; + +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_e_24000[16] = { + (Word16)0x0001, (Word16)0x0000, (Word16)0x0000, (Word16)0xffff, (Word16)0xffff, (Word16)0xfffe, + (Word16)0xfffe, (Word16)0xfffd, (Word16)0xfffd, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffb, + (Word16)0xfffb, (Word16)0xfffa, (Word16)0xfffa, (Word16)0xfff9}; +#else +#define lpc_warp_dee_emphasis_16_24000 NULL +#define lpc_warp_dee_emphasis_16_e_24000 NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_32000[16] = {0x4000, 0x55e1, 0x733b, 0x4d50, 0x67bd, 0x4599, + 0x5d64, 0x7d50, 0x5413, 0x70d0, 0x4bb0, 0x658f, + 0x4423, 0x5b6e, 0x7aaf, 0x524f}; + +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_e_32000[16] = { + (Word16)0x0001, (Word16)0x0000, (Word16)0xffff, (Word16)0xffff, (Word16)0xfffe, (Word16)0xfffe, + (Word16)0xfffd, (Word16)0xfffc, (Word16)0xfffc, (Word16)0xfffb, (Word16)0xfffb, (Word16)0xfffa, + (Word16)0xfffa, (Word16)0xfff9, (Word16)0xfff8, (Word16)0xfff8}; +#else +#define lpc_warp_dee_emphasis_16_32000 NULL +#define lpc_warp_dee_emphasis_16_e_32000 NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_48000[16] = {0x4000, 0x50c3, 0x65ea, 0x404e, 0x5126, 0x6666, + 0x409c, 0x5188, 0x66e3, 0x40eb, 0x51ec, 0x6760, + 0x413a, 0x524f, 0x67de, 0x4189}; + +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_e_48000[16] = { + (Word16)0x0001, (Word16)0x0000, (Word16)0xffff, (Word16)0xffff, (Word16)0xfffe, (Word16)0xfffd, + (Word16)0xfffd, (Word16)0xfffc, (Word16)0xfffb, (Word16)0xfffb, (Word16)0xfffa, (Word16)0xfff9, + (Word16)0xfff9, (Word16)0xfff8, (Word16)0xfff7, (Word16)0xfff7}; +#else +#define lpc_warp_dee_emphasis_16_48000 NULL +#define lpc_warp_dee_emphasis_16_e_48000 NULL +#endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_96000[16] = {0x4000, 0x4bf4, 0x5a23, 0x6af9, 0x7ef3, 0x4b54, + 0x5966, 0x6a18, 0x7de9, 0x4ab6, 0x58aa, 0x6939, + 0x7ce0, 0x4a19, 0x57f0, 0x685d}; + +RAM_ALIGN const Word16 lpc_warp_dee_emphasis_16_e_96000[16] = { + (Word16)0x0001, (Word16)0x0000, (Word16)0xffff, (Word16)0xfffe, (Word16)0xfffd, (Word16)0xfffd, + (Word16)0xfffc, (Word16)0xfffb, (Word16)0xfffa, (Word16)0xfffa, (Word16)0xfff9, (Word16)0xfff8, + (Word16)0xfff7, (Word16)0xfff7, (Word16)0xfff6, (Word16)0xfff5}; +# else +# define lpc_warp_dee_emphasis_16_96000 NULL +# define lpc_warp_dee_emphasis_16_e_96000 NULL +# endif + +RAM_ALIGN const Word16 *const lpc_warp_dee_emphasis[NUM_SAMP_FREQ] = { + lpc_warp_dee_emphasis_16_8000, lpc_warp_dee_emphasis_16_16000, lpc_warp_dee_emphasis_16_24000, + lpc_warp_dee_emphasis_16_32000, lpc_warp_dee_emphasis_16_48000, lpc_warp_dee_emphasis_16_96000}; +RAM_ALIGN const Word16 *const lpc_warp_dee_emphasis_e[NUM_SAMP_FREQ] = { + lpc_warp_dee_emphasis_16_e_8000, lpc_warp_dee_emphasis_16_e_16000, lpc_warp_dee_emphasis_16_e_24000, + lpc_warp_dee_emphasis_16_e_32000, lpc_warp_dee_emphasis_16_e_48000, lpc_warp_dee_emphasis_16_e_96000}; + +RAM_ALIGN const Word16 bands_nrg_scale[32] = {0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 bands_offset_48000_HR[65] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 25, + 27, 29, 31, 33, 36, 39, 42, 45, 48, 51, 55, 59, 63, 67, 72, 77, 83, 89, 95, 101, 108, 116, + 124, 133, 142, 152, 163, 174, 187, 200, 214, 229, 244, 262, 280, 299, 320, 343, 367, 392, 419, 449, 480}; + +RAM_ALIGN const Word16 bands_offset_96000_HR[65] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 33, 36, 39, 42, 46, 50, 54, 59, 64, 69, 75, 82, 89, 96, 104, 113, 122, 132, 143, 155, 168, 181, + 196, 213, 230, 249, 270, 292, 316, 342, 371, 401, 434, 470, 509, 551, 596, 646, 699, 757, 819, 887, 960}; + +RAM_ALIGN const Word16 *const bands_offset_HR[2] = {bands_offset_48000_HR, bands_offset_96000_HR}; + +RAM_ALIGN const Word16 bands_offset_48000_5ms_HR[56] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 21, 23, 25, 27, 29, 31, 33, 35, 38, 41, 44, 47, 50, 54, 58, 62, 66, 71, + 76, 81, 87, 93, 100, 107, 114, 122, 131, 140, 149, 160, 171, 183, 196, 209, 224, 240}; +RAM_ALIGN const Word16 bands_offset_96000_5ms_HR[59] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, + 23, 25, 27, 29, 31, 34, 37, 40, 44, 48, 52, 56, 61, 66, 71, 77, 83, 90, 98, 106, + 115, 124, 135, 146, 158, 171, 185, 200, 217, 235, 254, 275, 298, 323, 349, 378, 409, 443, 480}; + +RAM_ALIGN const Word16 *const bands_offset_5ms_HR[2] = {bands_offset_48000_5ms_HR, bands_offset_96000_5ms_HR}; + +RAM_ALIGN const Word16 bands_offset_48000_2_5ms_HR[46] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, + 27, 29, 31, 33, 35, 37, 40, 43, 46, 49, 53, 57, 61, 65, 69, 74, 79, 85, 91, 97, 104, 112, 120}; +RAM_ALIGN const Word16 bands_offset_96000_2_5ms_HR[50] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, + 35, 38, 41, 45, 49, 53, 57, 62, 67, 73, 79, 85, 92, 100, 108, 117, 127, 137, 149, 161, 174, 189, 204, 221, 240}; + +RAM_ALIGN const Word16 *const bands_offset_2_5ms_HR[2] = {bands_offset_48000_2_5ms_HR, bands_offset_96000_2_5ms_HR}; + +#ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 bands_offset_48000_7_5ms_HR[65] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 24, + 26, 28, 30, 32, 34, 36, 38, 41, 44, 47, 50, 53, 56, 60, 64, 68, 73, 78, 83, 89, 95, 101, 108, + 115, 122, 130, 139, 148, 158, 168, 179, 191, 203, 217, 231, 246, 262, 279, 298, 317, 338, 360}; +RAM_ALIGN const Word16 bands_offset_96000_7_5ms_HR[65] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, + 30, 32, 35, 38, 41, 44, 48, 52, 56, 61, 66, 71, 77, 83, 90, 97, 105, 114, 123, 132, 143, 155, 167, + 180, 195, 210, 227, 245, 265, 286, 309, 334, 360, 389, 420, 454, 490, 529, 572, 617, 667, 720}; + +RAM_ALIGN const Word16 *const bands_offset_7_5ms_HR[2] = {bands_offset_48000_7_5ms_HR, bands_offset_96000_7_5ms_HR}; +# endif +#endif /* ENABLE_HR_MODE */ + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 bands_offset_8000_lpc_warp[65] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, + 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, + 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, + 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0033, 0x0035, + 0x0037, 0x0039, 0x003b, 0x003d, 0x003f, 0x0041, 0x0043, 0x0045, 0x0047, 0x0049, 0x004b, 0x004d, 0x0050}; +#else +#define bands_offset_8000_lpc_warp NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 bands_offset_16000_lpc_warp[65] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, + 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, + 0x001a, 0x001b, 0x001c, 0x001e, 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030, + 0x0032, 0x0034, 0x0037, 0x003a, 0x003d, 0x0040, 0x0043, 0x0046, 0x0049, 0x004c, 0x0050, 0x0054, 0x0058, + 0x005c, 0x0060, 0x0065, 0x006a, 0x006f, 0x0074, 0x0079, 0x007f, 0x0085, 0x008b, 0x0092, 0x0099, 0x00a0}; +#else +#define bands_offset_16000_lpc_warp NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 bands_offset_24000_lpc_warp[65] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, + 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0019, 0x001b, + 0x001d, 0x001f, 0x0021, 0x0023, 0x0025, 0x0027, 0x0029, 0x002b, 0x002e, 0x0031, 0x0034, 0x0037, 0x003a, + 0x003d, 0x0040, 0x0044, 0x0048, 0x004c, 0x0050, 0x0055, 0x005a, 0x005f, 0x0064, 0x006a, 0x0070, 0x0076, + 0x007d, 0x0084, 0x008b, 0x0093, 0x009b, 0x00a4, 0x00ad, 0x00b7, 0x00c1, 0x00cc, 0x00d7, 0x00e3, 0x00f0}; +#else +#define bands_offset_24000_lpc_warp NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 bands_offset_32000_lpc_warp[65] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, + 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, + 0x0020, 0x0022, 0x0024, 0x0026, 0x0029, 0x002c, 0x002f, 0x0032, 0x0035, 0x0038, 0x003c, 0x0040, 0x0044, + 0x0048, 0x004c, 0x0051, 0x0056, 0x005b, 0x0061, 0x0067, 0x006d, 0x0074, 0x007b, 0x0083, 0x008b, 0x0094, + 0x009d, 0x00a6, 0x00b0, 0x00bb, 0x00c7, 0x00d3, 0x00e0, 0x00ee, 0x00fc, 0x010c, 0x011c, 0x012e, 0x0140}; +#else +#define bands_offset_32000_lpc_warp NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 bands_offset_48000_lpc_warp[65] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, + 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, 0x0020, + 0x0022, 0x0024, 0x0027, 0x002a, 0x002d, 0x0030, 0x0033, 0x0037, 0x003b, 0x003f, 0x0043, 0x0047, 0x004c, + 0x0051, 0x0056, 0x005c, 0x0062, 0x0069, 0x0070, 0x0077, 0x007f, 0x0087, 0x0090, 0x009a, 0x00a4, 0x00af, + 0x00ba, 0x00c6, 0x00d3, 0x00e1, 0x00f0, 0x0100, 0x0111, 0x0123, 0x0136, 0x014a, 0x0160, 0x0177, 0x0190}; +#else +#define bands_offset_48000_lpc_warp NULL +#endif + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 bands_offset_8000_lpc_lin[81] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, + 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, + 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, + 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 0x0050}; +#else +#define bands_offset_8000_lpc_lin NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 bands_offset_16000_lpc_lin[81] = { + 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 0x0010, 0x0012, 0x0014, 0x0016, 0x0018, 0x001a, + 0x001c, 0x001e, 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030, 0x0032, 0x0034, 0x0036, + 0x0038, 0x003a, 0x003c, 0x003e, 0x0040, 0x0042, 0x0044, 0x0046, 0x0048, 0x004a, 0x004c, 0x004e, 0x0050, 0x0052, + 0x0054, 0x0056, 0x0058, 0x005a, 0x005c, 0x005e, 0x0060, 0x0062, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, + 0x0070, 0x0072, 0x0074, 0x0076, 0x0078, 0x007a, 0x007c, 0x007e, 0x0080, 0x0082, 0x0084, 0x0086, 0x0088, 0x008a, + 0x008c, 0x008e, 0x0090, 0x0092, 0x0094, 0x0096, 0x0098, 0x009a, 0x009c, 0x009e, 0x00a0}; +#else +#define bands_offset_16000_lpc_lin NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 bands_offset_24000_lpc_lin[81] = { + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, 0x0018, 0x001b, 0x001e, 0x0021, 0x0024, 0x0027, + 0x002a, 0x002d, 0x0030, 0x0033, 0x0036, 0x0039, 0x003c, 0x003f, 0x0042, 0x0045, 0x0048, 0x004b, 0x004e, 0x0051, + 0x0054, 0x0057, 0x005a, 0x005d, 0x0060, 0x0063, 0x0066, 0x0069, 0x006c, 0x006f, 0x0072, 0x0075, 0x0078, 0x007b, + 0x007e, 0x0081, 0x0084, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, 0x0096, 0x0099, 0x009c, 0x009f, 0x00a2, 0x00a5, + 0x00a8, 0x00ab, 0x00ae, 0x00b1, 0x00b4, 0x00b7, 0x00ba, 0x00bd, 0x00c0, 0x00c3, 0x00c6, 0x00c9, 0x00cc, 0x00cf, + 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00de, 0x00e1, 0x00e4, 0x00e7, 0x00ea, 0x00ed, 0x00f0}; +#else +#define bands_offset_24000_lpc_lin NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 bands_offset_32000_lpc_lin[81] = { + 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, 0x001c, 0x0020, 0x0024, 0x0028, 0x002c, 0x0030, 0x0034, + 0x0038, 0x003c, 0x0040, 0x0044, 0x0048, 0x004c, 0x0050, 0x0054, 0x0058, 0x005c, 0x0060, 0x0064, 0x0068, 0x006c, + 0x0070, 0x0074, 0x0078, 0x007c, 0x0080, 0x0084, 0x0088, 0x008c, 0x0090, 0x0094, 0x0098, 0x009c, 0x00a0, 0x00a4, + 0x00a8, 0x00ac, 0x00b0, 0x00b4, 0x00b8, 0x00bc, 0x00c0, 0x00c4, 0x00c8, 0x00cc, 0x00d0, 0x00d4, 0x00d8, 0x00dc, + 0x00e0, 0x00e4, 0x00e8, 0x00ec, 0x00f0, 0x00f4, 0x00f8, 0x00fc, 0x0100, 0x0104, 0x0108, 0x010c, 0x0110, 0x0114, + 0x0118, 0x011c, 0x0120, 0x0124, 0x0128, 0x012c, 0x0130, 0x0134, 0x0138, 0x013c, 0x0140}; +#else +#define bands_offset_32000_lpc_lin NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 bands_offset_48000_lpc_lin[81] = { + 0x0000, 0x0006, 0x000c, 0x0012, 0x0018, 0x001e, 0x0024, 0x002a, 0x0030, 0x0036, 0x003c, 0x0042, 0x0048, 0x004e, + 0x0054, 0x005a, 0x0060, 0x0066, 0x006c, 0x0072, 0x0078, 0x007e, 0x0084, 0x008a, 0x0090, 0x0096, 0x009c, 0x00a2, + 0x00a8, 0x00ae, 0x00b4, 0x00ba, 0x00c0, 0x00c6, 0x00cc, 0x00d2, 0x00d8, 0x00de, 0x00e4, 0x00ea, 0x00f0, 0x00f6, + 0x00fc, 0x0102, 0x0108, 0x010e, 0x0114, 0x011a, 0x0120, 0x0126, 0x012c, 0x0132, 0x0138, 0x013e, 0x0144, 0x014a, + 0x0150, 0x0156, 0x015c, 0x0162, 0x0168, 0x016e, 0x0174, 0x017a, 0x0180, 0x0186, 0x018c, 0x0192, 0x0198, 0x019e, + 0x01a4, 0x01aa, 0x01b0, 0x01b6, 0x01bc, 0x01c2, 0x01c8, 0x01ce, 0x01d4, 0x01da, 0x01e0}; +#else +#define bands_offset_48000_lpc_lin NULL +#endif + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 bands_offset_8000_lpc_warp_5ms[40] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, + 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0028}; +#else +#define bands_offset_8000_lpc_warp_5ms NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 bands_offset_16000_lpc_warp_5ms[51] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, + 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, + 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, + 0x0030, 0x0032, 0x0034, 0x0036, 0x0039, 0x003c, 0x003f, 0x0042, 0x0045, 0x0048, 0x004c, 0x0050}; +#else +#define bands_offset_16000_lpc_warp_5ms NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 bands_offset_24000_lpc_warp_5ms[53] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, + 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x001a, 0x001c, 0x001e, + 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002f, 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, + 0x0045, 0x0049, 0x004d, 0x0051, 0x0056, 0x005b, 0x0060, 0x0065, 0x006b, 0x0071, 0x0078}; +#else +#define bands_offset_24000_lpc_warp_5ms NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 bands_offset_32000_lpc_warp_5ms[55] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, + 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, 0x0020, + 0x0022, 0x0024, 0x0026, 0x0028, 0x002a, 0x002d, 0x0030, 0x0033, 0x0036, 0x0039, 0x003d, 0x0041, 0x0045, 0x0049, + 0x004e, 0x0053, 0x0058, 0x005d, 0x0063, 0x0069, 0x0070, 0x0077, 0x007e, 0x0086, 0x008e, 0x0097, 0x00a0}; +#else +#define bands_offset_32000_lpc_warp_5ms NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 bands_offset_48000_lpc_warp_5ms[56] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, + 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0017, 0x0019, 0x001b, 0x001d, 0x001f, 0x0021, + 0x0023, 0x0025, 0x0028, 0x002b, 0x002e, 0x0031, 0x0034, 0x0037, 0x003b, 0x003f, 0x0043, 0x0048, 0x004d, 0x0052, + 0x0057, 0x005d, 0x0063, 0x0069, 0x0070, 0x0078, 0x0080, 0x0088, 0x0091, 0x009b, 0x00a5, 0x00b0, 0x00bb, 0x00c8}; +#else +#define bands_offset_48000_lpc_warp_5ms NULL +#endif + + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 bands_offset_8000_lpc_warp_2_5ms[21] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; +#else +#define bands_offset_8000_lpc_warp_2_5ms NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 bands_offset_16000_lpc_warp_2_5ms[36] = {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, 32, 34, 36, 38, 40}; +#else +#define bands_offset_16000_lpc_warp_2_5ms NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 bands_offset_24000_lpc_warp_2_5ms[41] = {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, 28, + 30, 32, 34, 36, 38, 40, 42, 44, 47, 50, 53, 56, 60}; +#else +#define bands_offset_24000_lpc_warp_2_5ms NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 bands_offset_32000_lpc_warp_2_5ms[44] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, 46, 49, 52, 55, 59, 63, 67, 71, 75, 80}; +#else +#define bands_offset_32000_lpc_warp_2_5ms NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 bands_offset_48000_lpc_warp_2_5ms[45] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, + 25, 27, 29, 31, 33, 35, 37, 40, 43, 46, 49, 52, 56, 60, 64, 68, 72, 77, 82, 87, 93, 100}; +#else +#define bands_offset_48000_lpc_warp_2_5ms NULL +#endif + + + +RAM_ALIGN const Word16 *const bands_offset[6] = {bands_offset_8000_lpc_warp, bands_offset_16000_lpc_warp, + bands_offset_24000_lpc_warp, bands_offset_32000_lpc_warp, + bands_offset_48000_lpc_warp, NULL}; + +#ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 bands_offset_with_one_max_7_5ms[NUM_OFFSETS] = {60, 34, 27, 24, 22 +# ifdef ENABLE_HR_MODE + , 20, 16 +# endif +}; +RAM_ALIGN const Word16 bands_offset_with_two_max_7_5ms[NUM_OFFSETS] = {0, 48, 38, 33, 31 +# ifdef ENABLE_HR_MODE + , 29, 24 +# endif +}; +# endif + +RAM_ALIGN const Word16 bands_offset_with_one_max[NUM_OFFSETS] = {49, 28, 23, 20, 18 +# ifdef ENABLE_HR_MODE + , 17, 12 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_two_max[NUM_OFFSETS] = {63, 40, 33, 29, 27 +# ifdef ENABLE_HR_MODE + , 25, 21 +# endif + }; + +RAM_ALIGN const Word16 *const bands_offset_5ms[6] = {bands_offset_8000_lpc_warp_5ms, bands_offset_16000_lpc_warp_5ms, + bands_offset_24000_lpc_warp_5ms, bands_offset_32000_lpc_warp_5ms, + bands_offset_48000_lpc_warp_5ms, NULL}; +RAM_ALIGN const Word16 bands_offset_with_one_max_5ms[NUM_OFFSETS] = {38, 30, 24, 22, 21 +# ifdef ENABLE_HR_MODE + , 19, 17 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_two_max_5ms[NUM_OFFSETS] = {39, 42, 34, 32, 29 +# ifdef ENABLE_HR_MODE + , 27, 24 +# endif + }; + +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 bands_number_7_5ms [] = {60, 64, 64, 64, 64, 64}; +# else +RAM_ALIGN const Word16 bands_number_7_5ms [] = {60, 64, 64, 64, 64}; +# endif +#endif + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 bands_number_5ms[NUM_SAMP_FREQ] = {39, 50, 52, 54, 55, 58}; +#else +RAM_ALIGN const Word16 bands_number_5ms[NUM_SAMP_FREQ] = {39, 50, 52, 54, 55}; +#endif + +RAM_ALIGN const Word16 *const bands_offset_2_5ms[6] = { + bands_offset_8000_lpc_warp_2_5ms, bands_offset_16000_lpc_warp_2_5ms, bands_offset_24000_lpc_warp_2_5ms, + bands_offset_32000_lpc_warp_2_5ms, bands_offset_48000_lpc_warp_2_5ms, NULL}; + +RAM_ALIGN const Word16 bands_offset_with_one_max_2_5ms[NUM_OFFSETS] = {20, 30, 26, 24, 21 +# ifdef ENABLE_HR_MODE + , 19, 16 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_two_max_2_5ms[NUM_OFFSETS] = {20, 35, 35, 32, 29 +# ifdef ENABLE_HR_MODE + , 28, 24 +# endif + }; + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 bands_number_2_5ms_HR[] = {20, 35, 40, 43, 45, 49}; +RAM_ALIGN const Word16 bands_number_2_5ms [] = {20, 35, 40, 43, 44, 49}; +# else +RAM_ALIGN const Word16 bands_number_2_5ms [] = {20, 35, 40, 43, 44}; +# endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 bands_offset_96000_lpc_lin[81] = +{ + 0x0000, 0x000c, 0x0018, 0x0024, 0x0030, 0x003c, 0x0048, 0x0054, 0x0060, 0x006c, 0x0078, 0x0084, 0x0090, 0x009c, + 0x00a8, 0x00b4, 0x00c0, 0x00cc, 0x00d8, 0x00e4, 0x00f0, 0x00fc, 0x0108, 0x0114, 0x0120, 0x012c, 0x0138, 0x0144, + 0x0150, 0x015c, 0x0168, 0x0174, 0x0180, 0x018c, 0x0198, 0x01a4, 0x01b0, 0x01bc, 0x01c8, 0x01d4, 0x01e0, 0x01ec, + 0x01f8, 0x0204, 0x0210, 0x021c, 0x0228, 0x0234, 0x0240, 0x024c, 0x0258, 0x0264, 0x0270, 0x027c, 0x0288, 0x0294, + 0x02a0, 0x02ac, 0x02b8, 0x02c4, 0x02d0, 0x02dc, 0x02e8, 0x02f4, 0x0300, 0x030c, 0x0318, 0x0324, 0x0330, 0x033c, + 0x0348, 0x0354, 0x0360, 0x036c, 0x0378, 0x0384, 0x0390, 0x039c, 0x03a8, 0x03b4, 0x03c0 +}; + +# ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 bands_offset_96000_lpc_lin_7_5ms[81] = +{ + 0x0000, 0x0009, 0x0012, 0x001b, 0x0024, 0x002d, 0x0036, 0x003f, 0x0048, 0x0051, 0x005a, 0x0063, 0x006c, 0x0075, + 0x007e, 0x0087, 0x0090, 0x0099, 0x00a2, 0x00ab, 0x00b4, 0x00bd, 0x00c6, 0x00cf, 0x00d8, 0x00e1, 0x00ea, 0x00f3, + 0x00fc, 0x0105, 0x010e, 0x0117, 0x0120, 0x0129, 0x0132, 0x013b, 0x0144, 0x014d, 0x0156, 0x015f, 0x0168, 0x0171, + 0x017a, 0x0183, 0x018c, 0x0195, 0x019e, 0x01a7, 0x01b0, 0x01b9, 0x01c2, 0x01cb, 0x01d4, 0x01dd, 0x01e6, 0x01ef, + 0x01f8, 0x0201, 0x020a, 0x0213, 0x021c, 0x0225, 0x022e, 0x0237, 0x0240, 0x0249, 0x0252, 0x025b, 0x0264, 0x026d, + 0x0276, 0x027f, 0x0288, 0x0291, 0x029a, 0x02a3, 0x02ac, 0x02b5, 0x02be, 0x02c7, 0x02d0 +}; +# endif +# endif + + +RAM_ALIGN const Word16 *const bands_offset_lin[NUM_SAMP_FREQ] = {bands_offset_8000_lpc_lin, bands_offset_16000_lpc_lin, + bands_offset_24000_lpc_lin, bands_offset_32000_lpc_lin, + bands_offset_48000_lpc_lin +# ifdef ENABLE_HR_MODE + , bands_offset_96000_lpc_lin +# endif + }; + +# ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 *const bands_offset_lin_7_5ms[NUM_SAMP_FREQ] = {bands_offset_8000_lpc_lin, bands_offset_16000_lpc_lin, + bands_offset_24000_lpc_lin, bands_offset_24000_lpc_lin, + bands_offset_48000_lpc_lin +# ifdef ENABLE_HR_MODE + , bands_offset_96000_lpc_lin_7_5ms +# endif + }; +# endif + +RAM_ALIGN const Word16 *const bands_offset_lin_5ms[NUM_SAMP_FREQ] = {bands_offset_8000_lpc_lin, bands_offset_8000_lpc_lin, + bands_offset_24000_lpc_lin, bands_offset_16000_lpc_lin, + bands_offset_24000_lpc_lin +# ifdef ENABLE_HR_MODE + , bands_offset_48000_lpc_lin +# endif + }; +RAM_ALIGN const Word16 *const bands_offset_lin_2_5ms[NUM_SAMP_FREQ] = {bands_offset_8000_lpc_lin, bands_offset_8000_lpc_lin, + bands_offset_8000_lpc_lin, bands_offset_8000_lpc_lin, + bands_offset_16000_lpc_lin +# ifdef ENABLE_HR_MODE + , bands_offset_24000_lpc_lin +# endif + }; + +RAM_ALIGN const Word16 bands_offset_with_one_max_lin[NUM_SAMP_FREQ] = {80, 0, 0, 0, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_two_max_lin[NUM_SAMP_FREQ] = {0, 80, 0, 0, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; + +# ifdef CR8_G_ADD_75MS +RAM_ALIGN const Word16 bands_offset_with_one_max_lin_7_5ms[NUM_SAMP_FREQ] = {60, 0, 0, 0, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; + +RAM_ALIGN const Word16 bands_offset_with_two_max_lin_7_5ms[NUM_SAMP_FREQ] = {0, 60, 0, 0, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; +#endif + +RAM_ALIGN const Word16 bands_offset_with_one_max_lin_5ms[NUM_SAMP_FREQ] = {40, 80, 0, 0, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_two_max_lin_5ms[NUM_SAMP_FREQ] = {0, 0, 0, 80, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_one_max_lin_2_5ms[NUM_SAMP_FREQ] = {20, 40, 60, 80, 0 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; +RAM_ALIGN const Word16 bands_offset_with_two_max_lin_2_5ms[NUM_SAMP_FREQ] = {0, 0, 0, 0, 60 +# ifdef ENABLE_HR_MODE + , 0 +# endif + }; +#ifdef CR8_G_ADD_75MS +# ifdef SUBSET_NB +RAM_ALIGN const Word16 bands_offset_8000_lpc_warp_7_5ms[61] = { + 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, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60}; +# else +# define bands_offset_8000_lpc_warp_7_5ms NULL +# endif + +# ifdef SUBSET_WB +RAM_ALIGN const Word16 bands_offset_16000_lpc_warp_7_5ms[65] = { + 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, 36, 38, 40, 42, 44, 46, 48, 50, 52, + 54, 56, 58, 60, 62, 65, 68, 71, 74, 77, 80, 83, 86, 90, 94, 98, 102, 106, 110, 115, 120}; +# else +# define bands_offset_16000_lpc_warp_7_5ms NULL +# endif + +# ifdef SUBSET_SSWB +RAM_ALIGN const Word16 bands_offset_24000_lpc_warp_7_5ms[65] = { + 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, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 52, 55, 58, 61, 64, + 67, 70, 74, 78, 82, 86, 90, 95, 100, 105, 110, 115, 121, 127, 134, 141, 148, 155, 163, 171, 180}; +# else +# define bands_offset_24000_lpc_warp_7_5ms NULL +# endif + +# ifdef SUBSET_SWB +RAM_ALIGN const Word16 bands_offset_32000_lpc_warp_7_5ms[65] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 45, 48, 51, 54, 57, 60, 63, 67, 71, 75, + 79, 84, 89, 94, 99, 105, 111, 117, 124, 131, 138, 146, 154, 163, 172, 182, 192, 203, 215, 227, 240}; +# else +# define bands_offset_32000_lpc_warp_7_5ms NULL +# endif + +# ifdef SUBSET_FB +RAM_ALIGN const Word16 bands_offset_48000_lpc_warp_7_5ms[65] = { + 0, 1, 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, 43, 46, 49, 52, 55, 59, 63, 67, 71, 75, 80, 85, + 90, 96, 102, 108, 115, 122, 129, 137, 146, 155, 165, 175, 186, 197, 209, 222, 236, 251, 266, 283, 300}; +# else +# define bands_offset_48000_lpc_warp_7_5ms NULL +# endif + +RAM_ALIGN const Word16 *const bands_offset_7_5ms[5] = { + bands_offset_8000_lpc_warp_7_5ms, bands_offset_16000_lpc_warp_7_5ms, bands_offset_24000_lpc_warp_7_5ms, + bands_offset_32000_lpc_warp_7_5ms, bands_offset_48000_lpc_warp_7_5ms}; +# endif /* ifdef CR8_G_ADD_75MS */ + +RAM_ALIGN const Word32 inv_odft_twiddle_80_re[M] = { + 0x7ff9af04, 0x7fe6bcb0, 0x7fc72ae2, 0x7f9afcb9, 0x7f62368f, 0x7f1cde01, 0x7ecaf9e5, 0x7e6c9251, + 0x7e01b096, 0x7d8a5f40, 0x7d06aa16, 0x7c769e18, 0x7bda497d, 0x7b31bbb2, 0x7a7d055b, 0x79bc384d}; + +RAM_ALIGN const Word32 inv_odft_twiddle_80_im[M] = { + 0x02835b5a, 0x05067734, 0x07891418, 0x0a0af299, 0x0c8bd35e, 0x0f0b7727, 0x11899ed3, 0x14060b68, + 0x16807e15, 0x18f8b83c, 0x1b6e7b7a, 0x1de189a6, 0x2051a4dd, 0x22be8f87, 0x25280c5e, 0x278dde6e}; + +RAM_ALIGN const Word32 inv_odft_twiddle_60_re[16] = { + 0x7ff4c56f, 0x7fd317b4, 0x7f9afcb9, 0x7f4c7e54, 0x7ee7aa4c, 0x7e6c9251, 0x7ddb4bfc, 0x7d33f0ca, + 0x7c769e18, 0x7ba3751d, 0x7aba9ae6, 0x79bc384d, 0x78a879f4, 0x777f903c, 0x7641af3d, 0x74ef0ebc}; + +RAM_ALIGN const Word32 inv_odft_twiddle_60_im[16] = { + 0x0359c428, 0x06b2f1d2, 0x0a0af299, 0x0d61304e, 0x10b5150f, 0x14060b68, 0x17537e63, 0x1a9cd9ac, + 0x1de189a6, 0x2120fb83, 0x245a9d65, 0x278dde6e, 0x2aba2ee4, 0x2ddf0040, 0x30fbc54d, 0x340ff242}; + +RAM_ALIGN const Word32 inv_odft_twiddle_40_re[16] = { + 0x7fe6bcb0, 0x7f9afcb9, 0x7f1cde01, 0x7e6c9251, 0x7d8a5f40, 0x7c769e18, 0x7b31bbb2, 0x79bc384d, + 0x7816a759, 0x7641af3d, 0x743e0918, 0x720c8075, 0x6fadf2fc, 0x6d23501b, 0x6a6d98a4, 0x678dde6e}; + +RAM_ALIGN const Word32 inv_odft_twiddle_40_im[16] = { + 0x05067734, 0x0a0af299, 0x0f0b7727, 0x14060b68, 0x18f8b83c, 0x1de189a6, 0x22be8f87, 0x278dde6e, + 0x2c4d9050, 0x30fbc54d, 0x3596a46c, 0x3a1c5c57, 0x3e8b240e, 0x42e13ba4, 0x471cece7, 0x4b3c8c12}; + +RAM_ALIGN const Word32 inv_odft_twiddle_20_re[16] = { + 0x7f9afcb9, 0x7e6c9251, 0x7c769e18, 0x79bc384d, 0x7641af3d, 0x720c8075, 0x6d23501b, 0x678dde6e, + 0x6154fb91, 0x5a82799a, 0x53211d18, 0x4b3c8c12, 0x42e13ba4, 0x3a1c5c57, 0x30fbc54d, 0x278dde6e}; + +RAM_ALIGN const Word32 inv_odft_twiddle_20_im[16] = { + 0x0a0af299, 0x14060b68, 0x1de189a6, 0x278dde6e, 0x30fbc54d, 0x3a1c5c57, 0x42e13ba4, 0x4b3c8c12, + 0x53211d18, 0x5a82799a, 0x6154fb91, 0x678dde6e, 0x6d23501b, 0x720c8075, 0x7641af3d, 0x79bc384d}; + +#ifdef SUBSET_NB +RAM_ALIGN const Word16 resamp_filt_8k[240] = { + 214, 417, -1052, -4529, 26233, -4529, -1052, 417, 214, 0, 212, 277, -1281, -3928, 26037, -4979, + -755, 550, 206, -8, 200, 136, -1439, -3214, 25456, -5243, -401, 668, 187, -18, 180, 0, + -1522, -2427, 24506, -5289, 0, 763, 156, -28, 154, -125, -1534, -1605, 23211, -5090, 432, 831, + 114, -39, 124, -234, -1478, -785, 21609, -4626, 877, 865, 61, -50, 92, -323, -1361, 0, + 19741, -3885, 1317, 861, 0, -61, 60, -391, -1194, 720, 17658, -2863, 1729, 815, -68, -69, + 29, -436, -987, 1351, 15414, -1563, 2093, 727, -140, -76, 0, -457, -752, 1873, 13068, 0, + 2389, 598, -213, -79, -25, -457, -501, 2274, 10677, 1803, 2597, 430, -282, -77, -46, -436, + -247, 2545, 8302, 3815, 2700, 229, -345, -72, -61, -398, 0, 2686, 5997, 5997, 2686, 0, + -398, -61, -72, -345, 229, 2700, 3815, 8302, 2545, -247, -436, -46, -77, -282, 430, 2597, + 1803, 10677, 2274, -501, -457, -25, -79, -213, 598, 2389, 0, 13068, 1873, -752, -457, 0, + -76, -140, 727, 2093, -1563, 15414, 1351, -987, -436, 29, -69, -68, 815, 1729, -2863, 17658, + 720, -1194, -391, 60, -61, 0, 861, 1317, -3885, 19741, 0, -1361, -323, 92, -50, 61, + 865, 877, -4626, 21609, -785, -1478, -234, 124, -39, 114, 831, 432, -5090, 23211, -1605, -1534, + -125, 154, -28, 156, 763, 0, -5289, 24506, -2427, -1522, 0, 180, -18, 187, 668, -401, + -5243, 25456, -3214, -1439, 136, 200, -8, 206, 550, -755, -4979, 26037, -3928, -1281, 277, 212}; +#else +#define resamp_filt_8k NULL +#endif + +#ifdef SUBSET_WB +RAM_ALIGN const Word16 resamp_filt_16k[240] = { + -61, 214, -398, 417, 0, -1052, 2686, -4529, 5997, 26233, 5997, -4529, 2686, -1052, 0, 417, + -398, 214, -61, 0, -72, 212, -345, 277, 229, -1281, 2700, -3928, 3815, 26037, 8302, -4979, + 2545, -755, -247, 550, -436, 206, -46, -8, -77, 200, -282, 136, 430, -1439, 2597, -3214, + 1803, 25456, 10677, -5243, 2274, -401, -501, 668, -457, 187, -25, -18, -79, 180, -213, 0, + 598, -1522, 2389, -2427, 0, 24506, 13068, -5289, 1873, 0, -752, 763, -457, 156, 0, -28, + -76, 154, -140, -125, 727, -1534, 2093, -1605, -1563, 23211, 15414, -5090, 1351, 432, -987, 831, + -436, 114, 29, -39, -69, 124, -68, -234, 815, -1478, 1729, -785, -2863, 21609, 17658, -4626, + 720, 877, -1194, 865, -391, 61, 60, -50, -61, 92, 0, -323, 861, -1361, 1317, 0, + -3885, 19741, 19741, -3885, 0, 1317, -1361, 861, -323, 0, 92, -61, -50, 60, 61, -391, + 865, -1194, 877, 720, -4626, 17658, 21609, -2863, -785, 1729, -1478, 815, -234, -68, 124, -69, + -39, 29, 114, -436, 831, -987, 432, 1351, -5090, 15414, 23211, -1563, -1605, 2093, -1534, 727, + -125, -140, 154, -76, -28, 0, 156, -457, 763, -752, 0, 1873, -5289, 13068, 24506, 0, + -2427, 2389, -1522, 598, 0, -213, 180, -79, -18, -25, 187, -457, 668, -501, -401, 2274, + -5243, 10677, 25456, 1803, -3214, 2597, -1439, 430, 136, -282, 200, -77, -8, -46, 206, -436, + 550, -247, -755, 2545, -4979, 8302, 26037, 3815, -3928, 2700, -1281, 229, 277, -345, 212, -72}; +#else +#define resamp_filt_16k NULL +#endif + +#ifdef SUBSET_SSWB +RAM_ALIGN const Word16 resamp_filt_24k[240] = { + -50, 19, 143, -93, -290, 278, 485, -658, -701, 1396, 901, -3019, -1042, 10276, 17488, 10276, + -1042, -3019, 901, 1396, -701, -658, 485, 278, -290, -93, 143, 19, -50, 0, -46, 0, + 141, -45, -305, 185, 543, -501, -854, 1153, 1249, -2619, -1908, 8712, 17358, 11772, 0, -3319, + 480, 1593, -504, -796, 399, 367, -261, -142, 138, 40, -52, -5, -41, -17, 133, 0, + -304, 91, 574, -334, -959, 878, 1516, -2143, -2590, 7118, 16971, 13161, 1202, -3495, 0, 1731, + -267, -908, 287, 445, -215, -188, 125, 62, -52, -12, -34, -30, 120, 41, -291, 0, + 577, -164, -1015, 585, 1697, -1618, -3084, 5534, 16337, 14406, 2544, -3526, -523, 1800, 0, -985, + 152, 509, -156, -230, 104, 83, -48, -19, -26, -41, 103, 76, -265, -83, 554, 0, + -1023, 288, 1791, -1070, -3393, 3998, 15474, 15474, 3998, -3393, -1070, 1791, 288, -1023, 0, 554, + -83, -265, 76, 103, -41, -26, -19, -48, 83, 104, -230, -156, 509, 152, -985, 0, + 1800, -523, -3526, 2544, 14406, 16337, 5534, -3084, -1618, 1697, 585, -1015, -164, 577, 0, -291, + 41, 120, -30, -34, -12, -52, 62, 125, -188, -215, 445, 287, -908, -267, 1731, 0, + -3495, 1202, 13161, 16971, 7118, -2590, -2143, 1516, 878, -959, -334, 574, 91, -304, 0, 133, + -17, -41, -5, -52, 40, 138, -142, -261, 367, 399, -796, -504, 1593, 480, -3319, 0, + 11772, 17358, 8712, -1908, -2619, 1249, 1153, -854, -501, 543, 185, -305, -45, 141, 0, -46}; +#else +#define resamp_filt_24k NULL +#endif + +#ifdef SUBSET_SWB +RAM_ALIGN const Word16 resamp_filt_32k[240] = { + -30, -31, 46, 107, 0, -199, -162, 209, 430, 0, -681, -526, 658, 1343, 0, -2264, + -1943, 2999, 9871, 13116, 9871, 2999, -1943, -2264, 0, 1343, 658, -526, -681, 0, 430, 209, + -162, -199, 0, 107, 46, -31, -30, 0, -25, -36, 30, 106, 31, -173, -195, 139, + 432, 114, -597, -641, 439, 1350, 360, -1964, -2313, 1908, 8829, 13019, 10804, 4151, -1431, -2489, + -393, 1273, 864, -378, -739, -123, 408, 275, -117, -218, -34, 103, 62, -23, -35, -4, + -20, -39, 14, 100, 57, -141, -218, 68, 416, 215, -494, -719, 216, 1298, 676, -1607, + -2545, 902, 7707, 12728, 11606, 5339, -781, -2621, -803, 1137, 1047, -200, -767, -251, 364, 334, + -62, -228, -70, 94, 77, -13, -38, -9, -14, -39, 0, 90, 78, -106, -229, 0, + 382, 299, -376, -761, 0, 1194, 937, -1214, -2644, 0, 6534, 12253, 12253, 6534, 0, -2644, + -1214, 937, 1194, 0, -761, -376, 299, 382, 0, -229, -106, 78, 90, 0, -39, -14, + -9, -38, -13, 77, 94, -70, -228, -62, 334, 364, -251, -767, -200, 1047, 1137, -803, + -2621, -781, 5339, 11606, 12728, 7707, 902, -2545, -1607, 676, 1298, 216, -719, -494, 215, 416, + 68, -218, -141, 57, 100, 14, -39, -20, -4, -35, -23, 62, 103, -34, -218, -117, + 275, 408, -123, -739, -378, 864, 1273, -393, -2489, -1431, 4151, 10804, 13019, 8829, 1908, -2313, + -1964, 360, 1350, 439, -641, -597, 114, 432, 139, -195, -173, 31, 106, 30, -36, -25}; +#else +#define resamp_filt_32k NULL +#endif + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 resamp_filt_96k[240] = { + -3, -7, -10, -13, -13, -10, -4, 5, 15, 26, 33, 36, 31, 19, 0, -23, -47, -66, -76, + -73, -54, -21, 23, 70, 111, 139, 143, 121, 72, 0, -84, -165, -227, -256, -240, -175, -67, 72, + 219, 349, 433, 448, 379, 225, 0, -268, -536, -755, -874, -848, -648, -260, 301, 1000, 1780, 2569, 3290, + 3869, 4243, 4372, 4243, 3869, 3290, 2569, 1780, 1000, 301, -260, -648, -848, -874, -755, -536, -268, 0, 225, + 379, 448, 433, 349, 219, 72, -67, -175, -240, -256, -227, -165, -84, 0, 72, 121, 143, 139, 111, + 70, 23, -21, -54, -73, -76, -66, -47, -23, 0, 19, 31, 36, 33, 26, 15, 5, -4, -10, + -13, -13, -10, -7, -3, 0, -1, -5, -8, -12, -13, -12, -8, 0, 10, 21, 30, 35, 34, + 26, 10, -11, -35, -58, -73, -76, -65, -39, 0, 46, 92, 127, 144, 136, 100, 38, -41, -125, + -199, -246, -254, -214, -126, 0, 146, 288, 398, 450, 424, 312, 120, -131, -405, -655, -830, -881, -771, + -477, 0, 636, 1384, 2178, 2943, 3601, 4084, 4340, 4340, 4084, 3601, 2943, 2178, 1384, 636, 0, -477, -771, + -881, -830, -655, -405, -131, 120, 312, 424, 450, 398, 288, 146, 0, -126, -214, -254, -246, -199, -125, + -41, 38, 100, 136, 144, 127, 92, 46, 0, -39, -65, -76, -73, -58, -35, -11, 10, 26, 34, + 35, 30, 21, 10, 0, -8, -12, -13, -12, -8, -5, -1}; +#else +# define resamp_filt_96k NULL +#endif + +#ifdef SUBSET_FB +RAM_ALIGN const Word16 resamp_filt_48k[240] = { + -13, -25, -20, 10, 51, 71, 38, -47, -133, -145, -42, 139, 277, 242, 0, -329, + -511, -351, 144, 698, 895, 450, -535, -1510, -1697, -521, 1999, 5138, 7737, 8744, 7737, 5138, + 1999, -521, -1697, -1510, -535, 450, 895, 698, 144, -351, -511, -329, 0, 242, 277, 139, + -42, -145, -133, -47, 38, 71, 51, 10, -20, -25, -13, 0, -9, -23, -24, 0, + 41, 71, 52, -23, -115, -152, -78, 92, 254, 272, 76, -251, -493, -427, 0, 576, + 900, 624, -262, -1309, -1763, -954, 1272, 4356, 7203, 8679, 8169, 5886, 2767, 0, -1542, -1660, + -809, 240, 848, 796, 292, -252, -507, -398, -82, 199, 288, 183, 0, -130, -145, -71, + 20, 69, 60, 20, -15, -26, -17, -3, -6, -20, -26, -8, 31, 67, 62, 0, + -94, -152, -108, 45, 223, 287, 143, -167, -454, -480, -134, 439, 866, 758, 0, -1071, + -1748, -1295, 601, 3559, 6580, 8485, 8485, 6580, 3559, 601, -1295, -1748, -1071, 0, 758, 866, + 439, -134, -480, -454, -167, 143, 287, 223, 45, -108, -152, -94, 0, 62, 67, 31, + -8, -26, -20, -6, -3, -17, -26, -15, 20, 60, 69, 20, -71, -145, -130, 0, + 183, 288, 199, -82, -398, -507, -252, 292, 796, 848, 240, -809, -1660, -1542, 0, 2767, + 5886, 8169, 8679, 7203, 4356, 1272, -954, -1763, -1309, -262, 624, 900, 576, 0, -427, -493, + -251, 76, 272, 254, 92, -78, -152, -115, -23, 52, 71, 41, 0, -24, -23, -9}; +#else +#define resamp_filt_48k NULL +#endif + + +RAM_ALIGN const Word16 *const resamp_filts[NUM_SAMP_FREQ] = {resamp_filt_8k, + resamp_filt_16k, + resamp_filt_24k, + resamp_filt_32k, + resamp_filt_48k, + resamp_filt_96k +}; + +RAM_ALIGN const Word16 resamp_params[NUM_SAMP_FREQ][4] = { +#ifdef SUBSET_NB + {24, 5, 0, 15}, +#else + {0}, +#endif +#ifdef SUBSET_WB + {12, 10, 1, 3}, +#else + {0}, +#endif +#ifdef SUBSET_SSWB + {8, 15, 1, 7}, +#else + {0}, +#endif +#ifdef SUBSET_SWB + {6, 20, 2, 3}, +#else + {0}, +#endif +#ifdef SUBSET_FB + {4, 30, 3, 3}, +#else + {0}, +#endif +#ifdef ENABLE_HR_MODE + {2, 60, 7, 1}, +#endif +}; + +RAM_ALIGN const Word16 highpass50_filt_num[3] = {32204, -32204, 32204}; +RAM_ALIGN const Word16 highpass50_filt_den[2] = {32199, -31650}; + +RAM_ALIGN const Word16 olpa_ac_weighting[98] = { + 32767, 32598, 32429, 32260, 32091, 31922, 31754, 31585, 31416, 31247, 31078, 30909, 30740, 30571, + 30402, 30233, 30065, 29896, 29727, 29558, 29389, 29220, 29051, 28882, 28713, 28544, 28376, 28207, + 28038, 27869, 27700, 27531, 27362, 27193, 27024, 26855, 26687, 26518, 26349, 26180, 26011, 25842, + 25673, 25504, 25335, 25166, 24998, 24829, 24660, 24491, 24322, 24153, 23984, 23815, 23646, 23477, + 23308, 23140, 22971, 22802, 22633, 22464, 22295, 22126, 21957, 21788, 21619, 21451, 21282, 21113, + 20944, 20775, 20606, 20437, 20268, 20099, 19930, 19762, 19593, 19424, 19255, 19086, 18917, 18748, + 18579, 18410, 18241, 18073, 17904, 17735, 17566, 17397, 17228, 17059, 16890, 16721, 16552, 16384}; + +RAM_ALIGN const Word16 ltpf_ac_interp_filt[7][9] = { + {90, 151, -2472, 26787, 10819, -3468, 940, -94, 0}, {-98, 967, -4270, 19769, 19769, -4270, 967, -98, 0}, + {-94, 940, -3468, 10819, 26787, -2472, 151, 90, 0}, {0, 503, -1550, 2739, 29447, 2739, -1550, 503, 0}, + {0, 90, 151, -2472, 26787, 10819, -3468, 940, -94}, {0, -98, 967, -4270, 19769, 19769, -4270, 967, -98}, + {0, -94, 940, -3468, 10819, 26787, -2472, 151, 90}}; + +RAM_ALIGN const Word16 inter_filter[5][4][12] = { + {{6877, 19121, 6877, 0}, {3506, 18025, 11000, 220}, {1300, 15048, 15048, 1300}, {220, 11000, 18025, 3506}}, + {{6877, 19121, 6877, 0}, {3506, 18025, 11000, 220}, {1300, 15048, 15048, 1300}, {220, 11000, 18025, 3506}}, + {{2072, 8216, 12170, 8216, 2072, 0}, + {1134, 6509, 11883, 9787, 3320, 140}, + {503, 4831, 11057, 11057, 4831, 503}, + {140, 3320, 9787, 11883, 6509, 1134}}, + {{950, 3702, 7248, 8926, 7248, 3702, 950, 0}, + {558, 2858, 6427, 8812, 7946, 4606, 1466, 102}, + {281, 2106, 5530, 8479, 8479, 5530, 2106, 281}, + {102, 1466, 4606, 7946, 8812, 6427, 2858, 558}}, + {{355, 1183, 2515, 4068, 5333, 5822, 5333, 4068, 2515, 1183, 355, 0}, + {231, 924, 2145, 3685, 5074, 5791, 5543, 4433, 2900, 1474, 510, 67}, + {136, 700, 1797, 3293, 4771, 5697, 5697, 4771, 3293, 1797, 700, 136}, + {67, 510, 1474, 2900, 4433, 5543, 5791, 5074, 3685, 2145, 924, 231}}}; +RAM_ALIGN const Word16 inter_filter_shift[5] = {1, 1, 2, 3, 5}; +RAM_ALIGN const Word16 inter_filter_len[5] = {4, 4, 6, 8, 12}; + +RAM_ALIGN const Word16 tilt_filter[5][4][11] = { + {{16777, 11692, -525}, {16697, 11692, -444}, {16622, 11692, -369}, {16551, 11692, -298}}, + {{16777, 11692, -525}, {16697, 11692, -444}, {16622, 11692, -369}, {16551, 11692, -298}}, + {{11112, 14323, 2797, -356, -44}, + {10998, 14271, 2906, -304, -38}, + {10890, 14222, 3008, -255, -32}, + {10788, 14175, 3104, -208, -26}}, + {{8307, 12959, 5866, 1049, -283, -71, -9}, + {8199, 12866, 5931, 1133, -242, -61, -8}, + {8098, 12777, 5992, 1212, -203, -51, -6}, + {8002, 12693, 6050, 1287, -166, -42, -5}}, + {{5519, 9817, 7001, 3967, 1589, 259, -201, -88, -31, -8, -1}, + {5433, 9706, 6991, 4014, 1651, 309, -172, -76, -27, -7, -1}, + {5353, 9601, 6981, 4058, 1710, 356, -145, -64, -23, -6, -1}, + {5277, 9501, 6970, 4100, 1767, 402, -118, -52, -19, -5, -1}}}; +RAM_ALIGN const Word16 tilt_filter_len[5] = {2, 2, 4, 6, 10}; + +RAM_ALIGN const Word16 gain_scale_fac[4] = {13108, 11468, 9832, 8192}; + +RAM_ALIGN const UWord16 pitch_scale[NUM_SAMP_FREQ] = {5120, + 10240, + 15360, + 20480, + 30720 +}; + +RAM_ALIGN const Word16 ltpf_overlap_len[NUM_SAMP_FREQ] = {20, 40, 60, 80, 120 +}; + +/* set up of SNS VQ stages 1 ( split VQ) and SNS stage 2(Transformed PVQ) for bit rate 38 bits */ + +/* trained gain set for DCT Q12 */ +RAM_ALIGN const Word16 sns_vq_reg_adj_gains[2] = {8915, 12054}; +RAM_ALIGN const Word16 sns_vq_reg_lf_adj_gains[4] = {6245, 15043, 17861, 21014}; +RAM_ALIGN const Word16 sns_vq_near_adj_gains[4] = {7099, 9132, 11253, 14808}; +RAM_ALIGN const Word16 sns_vq_far_adj_gains[8] = {4336, 5067, 5895, 8149, 10235, 12825, 16868, 19882}; + +RAM_ALIGN const Word16 *const sns_gaintabPtr[4] = {sns_vq_reg_adj_gains, sns_vq_reg_lf_adj_gains, sns_vq_near_adj_gains, + sns_vq_far_adj_gains}; +RAM_ALIGN const Word16 sns_gainSz[4] = {2, 4, 4, 8}; +RAM_ALIGN const Word16 sns_gainMSBbits[4] = {1, 1, 2, 2}; +RAM_ALIGN const Word16 sns_gainLSBbits[4] = {0, 1, 0, 1}; +RAM_ALIGN const Word16 sns_Kval[4][2] = {{10, 1}, {10, 0}, {8, 0}, {6, 0}}; +RAM_ALIGN const UWord32 sns_MPVQ_Sz[4][2] = { + {4780008U >> 1, (2U * 6U)}, {4780008U >> 1, (2U)}, {30316544U >> 1, 0U}, {MPVQ_SZ_OUTL_FAR, 0U}}; + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 st1SCF0_7_base5_32x8_Q27[256] = { + 303712392, 109160791, -71161366, -182086260, -214684177, -193406093, -153520450, -101361734, 395293327, + 323657083, 128910102, -59488852, -164971858, -208829415, -200908713, -149907762, -293414324, -264613117, + -239872071, -257518046, -240785425, -182185002, -94683128, -6417929, 93105259, 128259784, 77206169, + -15381811, -86711449, -127822437, -144156883, -101748810, -174150364, -99370653, -46355110, -42048494, + -54086690, -49931794, -10514807, 13025043, 122762518, 233932163, 256230537, 207243559, 146760322, + 86903234, 4855873, -39875122, -337462040, -388124479, -269040331, -100785739, 59217144, 161317613, + 178164447, 163811504, -123774032, 84892061, 145943568, 81688751, 17605952, -39748467, -27784884, + 18109316, 106075262, 84342590, 52763395, 64425544, 60104730, 28150050, 881397, -11559399, + 194314494, 365609026, 310154713, 125500457, -36875504, -121074819, -126256135, -85053377, 106482242, + 1931812, -76213503, -87880462, -64351897, -23339746, 9128989, 39611134, 365643112, 397214108, + 248240465, 75602822, 18779354, 48270210, 92537937, 85871184, -71246823, -28546860, 773918, + 57025285, 63502293, 115278828, 159868294, 133706314, 226463440, 326973859, 312753384, 238885783, + 193825560, 204004473, 197567682, 131222320, -396188282, -213934330, -14753048, 52158227, 68844655, + 84303846, 110410429, 117560157, 13673880, 79169310, 83087169, 170095890, 324754621, 302223766, + 70670604, -53229612, 360045196, 178157942, 17473172, -45437142, -49421549, -25728189, -20774539, + -31434755, 647866186, 418689256, 187252080, 33594069, -52829955, -86363494, -86244384, -97065351, + 11789953, -76448652, -153687373, -224101311, -247677903, -210007831, -149983961, -71669806, 186699958, + 265947702, 149338424, -29542330, -104014124, -79733903, 18379464, 109822702, 51618245, -21553862, + -72392588, -71042662, 25559558, 343681831, 378354941, 88136873, 259345425, 404035869, 411436250, + 335692175, 259160465, 76793185, -108950139, -157896166, 23498902, -100733469, -139511132, -152441152, + -139852059, -2040916, 277895647, 460298246, -159473505, 49230106, 175768625, 225929624, 167907618, + 126483532, 110897463, 59049457, 340003306, 283568025, 169501437, 102208613, 70077483, 15928969, + -60712963, -93999711, 536723054, 547476463, 378877401, 231669479, 86858248, -44446002, -118654185, + -151259810, 68169532, 213189358, 232061142, 135146824, 50616355, 63937402, 145968142, 145970189, + 425278032, 437353108, 325116396, 240848448, 204249734, 157298757, 65685431, -8359023, 254228196, + 167918047, 79249020, 81652507, 117866118, 150206430, 136711039, 83275912, 127356599, 286205131, + 365535742, 371764419, 341298198, 271181905, 111406869, -3698627, -252365241, -169692913, 41798753, + 246517983, 302841086, 274903406, 294643934, 272005129, 33067993, 128261383, 204073729, 265277850, + 260441270, 299809987, 266873132, 170768802 }; +RAM_ALIGN const Word32 st1SCF8_15_base5_32x8_Q27[256] = { + 31142327, -135412629, -287525918, -318812488, -299361815, -292052248, -307447065, -339955249, -173817241, + -241497912, -253273077, -242922894, -236679593, -246180047, -242237472, -233108740, 18694612, -34653021, + -87349511, -143365648, -217337078, -293618146, -354009441, -399831591, -42481669, -64122205, -73975722, + -65067182, -31995949, -19196424, 9169576, 11852254, 118046962, 40042530, -122861082, -296146014, + -367947407, -384049364, -387676629, -396187390, -39822658, -130862945, -182344850, -132032812, -87638397, + -132873805, -216717640, -323078583, 45765709, 36091119, 7560964, 6698995, -12806126, -102027773, + -312402661, -506209524, -189555374, -199343014, -159187030, -83886299, 20656444, 77361286, 106715523, + 80069550, -30714319, -44791015, -108625274, -219563932, -252982160, -220783722, -188597085, -196852406, + -143812455, -190276467, -207892204, -195013074, -138489838, -92696486, -57558441, -66432436, -79321135, + -9552782, 46401689, 40339066, -150142954, -327610913, -299110559, -254354980, -113874897, -78279377, + 12085282, 113417337, 143039033, 98996714, 34438988, -66030204, 153101016, 129388157, 51198856, + -64806941, -243783312, -376184794, -434040973, -464270818, -50503881, 5713319, 69329858, 33784868, + -29015184, -71682211, -86004854, -116735202, 89255342, 147358670, 185680385, 180291129, 110458350, + 28974493, -54348215, -143647337, -110899539, -90084420, -30668159, 69656431, 183505023, 292625568, + 340370914, 295441538, 189258173, 101259479, -175222029, -251166616, -166441640, -170071209, -273362338, + -388808843, 48504518, -2952679, -77761569, -118034823, -114177011, -104608901, -98271929, -119232119, + 58716127, 40995519, -991583, -66524997, -108266901, -164325304, -228381893, -301307946, 86986552, + 91576640, 33990299, 9876306, 42173453, 31504911, 19407902, -9155262, 150216257, 165712633, + 79077091, -184136602, -318224471, -269482063, -223725572, -258546087, 19038449, -14852543, -37960074, + -885587, 38376778, 6179995, -80879122, -304095400, 67652037, 110995667, 150298671, 158261551, + 144938274, 93621729, -122480229, -480076341, -67253289, -43711762, 3768810, 35172367, 48397679, + 85311972, 128716474, 175483179, 503277534, 204470792, -61433556, -107201177, -51918012, -50452587, + -88293374, -172018761, -154697999, -148714432, -75512923, -29603347, -46955117, -101124035, -132687189, + -172859645, 138012394, 147331497, 103165859, 27659855, -46010607, -101326252, -139849742, -201777098, + 17291535, 92534989, 150789463, 175737342, 181881080, 191007103, 155298567, 54535272, 179896088, + 186558381, 140214471, 85338684, -36874140, -207934631, -327812990, -405951728, 287015358, 570037814, + 388874539, 125188990, -39301937, -108770623, -105880084, -125540975, 75810265, 213654461, 321816127, + 407615675, 357588710, 186971315, 54201685, -88083199, -56701695, 43775062, 186792575, 299502316, + 350549113, 357744389, 322261535, 236116337 }; +#endif + +RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256] = { + 4634, 1666, -1086, -2778, -3276, -2951, -2343, -1547, 6032, 4939, 1967, -908, -2517, -3186, -3066, -2287, + -4477, -4038, -3660, -3929, -3674, -2780, -1445, -98, 1421, 1957, 1178, -235, -1323, -1950, -2200, -1553, + -2657, -1516, -707, -642, -825, -762, -160, 199, 1873, 3570, 3910, 3162, 2239, 1326, 74, -608, + -5149, -5922, -4105, -1538, 904, 2462, 2719, 2500, -1889, 1295, 2227, 1246, 269, -607, -424, 276, + 1619, 1287, 805, 983, 917, 430, 13, -176, 2965, 5579, 4733, 1915, -563, -1847, -1927, -1298, + 1625, 29, -1163, -1341, -982, -356, 139, 604, 5579, 6061, 3788, 1154, 287, 737, 1412, 1310, + -1087, -436, 12, 870, 969, 1759, 2439, 2040, 3456, 4989, 4772, 3645, 2958, 3113, 3015, 2002, + -6045, -3264, -225, 796, 1050, 1286, 1685, 1794, 209, 1208, 1268, 2595, 4955, 4612, 1078, -812, + 5494, 2718, 267, -693, -754, -393, -317, -480, 9886, 6389, 2857, 513, -806, -1318, -1316, -1481, + 180, -1167, -2345, -3420, -3779, -3204, -2289, -1094, 2849, 4058, 2279, -451, -1587, -1217, 280, 1676, + 788, -329, -1105, -1084, 390, 5244, 5773, 1345, 3957, 6165, 6278, 5122, 3954, 1172, -1662, -2409, + 359, -1537, -2129, -2326, -2134, -31, 4240, 7024, -2433, 751, 2682, 3447, 2562, 1930, 1692, 901, + 5188, 4327, 2586, 1560, 1069, 243, -926, -1434, 8190, 8354, 5781, 3535, 1325, -678, -1811, -2308, + 1040, 3253, 3541, 2062, 772, 976, 2227, 2227, 6489, 6673, 4961, 3675, 3117, 2400, 1002, -128, + 3879, 2562, 1209, 1246, 1798, 2292, 2086, 1271, 1943, 4367, 5578, 5673, 5208, 4138, 1700, -56, + -3851, -2589, 638, 3762, 4621, 4195, 4496, 4150, 505, 1957, 3114, 4048, 3974, 4575, 4072, 2606}; + +RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256] = { + 475, -2066, -4387, -4865, -4568, -4456, -4691, -5187, -2652, -3685, -3865, -3707, -3611, -3756, -3696, -3557, + 285, -529, -1333, -2188, -3316, -4480, -5402, -6101, -648, -978, -1129, -993, -488, -293, 140, 181, + 1801, 611, -1875, -4519, -5614, -5860, -5915, -6045, -608, -1997, -2782, -2015, -1337, -2027, -3307, -4930, + 698, 551, 115, 102, -195, -1557, -4767, -7724, -2892, -3042, -2429, -1280, 315, 1180, 1628, 1222, + -469, -683, -1657, -3350, -3860, -3369, -2878, -3004, -2194, -2903, -3172, -2976, -2113, -1414, -878, -1014, + -1210, -146, 708, 616, -2291, -4999, -4564, -3881, -1738, -1194, 184, 1731, 2183, 1511, 525, -1008, + 2336, 1974, 781, -989, -3720, -5740, -6623, -7084, -771, 87, 1058, 516, -443, -1094, -1312, -1781, + 1362, 2249, 2833, 2751, 1685, 442, -829, -2192, -1692, -1375, -468, 1063, 2800, 4465, 5194, 4508, + 2888, 1545, -2674, -3832, -2540, -2595, -4171, -5933, 740, -45, -1187, -1801, -1742, -1596, -1500, -1819, + 896, 626, -15, -1015, -1652, -2507, -3485, -4598, 1327, 1397, 519, 151, 644, 481, 296, -140, + 2292, 2529, 1207, -2810, -4856, -4112, -3414, -3945, 291, -227, -579, -14, 586, 94, -1234, -4640, + 1032, 1694, 2293, 2415, 2212, 1429, -1869, -7325, -1026, -667, 58, 537, 738, 1302, 1964, 2678, + 7679, 3120, -937, -1636, -792, -770, -1347, -2625, -2361, -2269, -1152, -452, -716, -1543, -2025, -2638, + 2106, 2248, 1574, 422, -702, -1546, -2134, -3079, 264, 1412, 2301, 2682, 2775, 2915, 2370, 832, + 2745, 2847, 2140, 1302, -563, -3173, -5002, -6194, 4380, 8698, 5934, 1910, -600, -1660, -1616, -1916, + 1157, 3260, 4911, 6220, 5456, 2853, 827, -1344, -865, 668, 2850, 4570, 5349, 5459, 4917, 3603}; + +/* tables for MPVQ pulse enumeration */ + +/* N=16, K=12 31.74 bits */ +RAM_ALIGN const UWord32 h_memN16K12[12 + 2] = { + 0U, 1U, 31U, 481U, 4991U, 39041U, 246047U, + 1303777U, 5984767U, 24331777U, 89129247U, 298199265U, 921406335U, /*U*/ 1326824512U}; + +/*N=16,K=8,h_memN16K8={0U,1U,31U,481U,4991U,39041U,246047U,1303777U,5984767U, 12165888U,}; */ + +/*N=10, K=20 +UWord32 h_memN10K20[20+2] = +{ + 0U,1U,19U,181U,1159U,5641U,22363U,75517U,224143U,598417U,1462563U, + 3317445U,7059735U,14218905U,27298155U,50250765U,89129247U,152951073U,254831667U,413442773U,654862247U, + 507444884U +}; +*/ +/*N=10, K=22 31.84 bits */ +RAM_ALIGN const UWord32 h_memN10K22[22 + 2] = {0U, + 1U, + 19U, + 181U, + 1159U, + 5641U, + 22363U, + 75517U, + 224143U, + 598417U, + 1462563U, + 3317445U, + 7059735U, + 14218905U, + 27298155U, + 50250765U, + 89129247U, + 152951073U, + 254831667U, + 413442773U, + 654862247U, + 1014889769U, + 1541911931U, + /*U*/ 1150204814U}; +/* N=10,K=10,h_memN10K10={0U,1U,19U,181U,1159U,5641U,22363U,75517U,224143U,598417U,1462563U,1658722U,}; */ + +/* N=6,K=2,*/ +RAM_ALIGN const UWord32 h_memN6K2[2 + 2] = {0U, 1U, 11U, /*U*/ 30U}; +/*N=6,K=1, h_memN6K1={0U,1U, 5U,}; */ + +RAM_ALIGN const UWord32 *const MPVQ_offs_ptr[M + 1] = {NULL /*0*/, NULL, NULL, NULL, NULL, NULL, + h_memN6K2, NULL, NULL, NULL, h_memN10K22, NULL, + NULL, NULL, NULL, NULL, h_memN16K12}; + +/*maxK coefficents for MPVQ de-indexing lookup */ +RAM_ALIGN const Word16 tabledKMAX[M + 1] = { + 0, 0, 0, 0, 0, 0, 2 /*N=6*/, 0, 0, 0, 22 /*N=10*/, 0, 0, 0, 0, 0, 12 /*N=16*/ +}; + +RAM_ALIGN const Word16 isqrt_Q16tab[1 + 64] = {/*table generated using ISqrt16 function + shift to Q16 */ + 32767, 32767, 32767, 32767, 32766, 29308, 26754, 24770, 23169, 21844, + 20723, 19759, 18918, 18176, 17515, 16921, 16383, 15894, 15446, 15034, + 14654, 14300, 13972, 13665, 13377, 13107, 12852, 12612, 12385, 12169, + 11965, 11770, 11584, 11407, 11238, 11077, 10922, 10773, 10631, 10493, + 10361, 10234, 10112, 9993, 9879, 9769, 9662, 9559, 9459, 9362, + 9268, 9176, 9088, 9001, 8918, 8836, 8757, 8680, 8605, 8532, + 8460, 8390, 8323, 8256, 8191}; + +#ifdef ENABLE_HR_MODE +RAM_ALIGN const Word32 isqrt_Q31tab[1 + 64] = {/* 2^31 / sqrt(idx) */ + 2147483647, 2147483647, 1518500249, 1239850262, 1073741824, 960383883, + 876706528, 811672525, 759250124, 715827882, 679093956, 647490682, + 619925131, 595604800, 573939146, 554477893, 536870912, 520841288, + 506166749, 492666537, 480191941, 468619350, 457845052, 447781294, + 438353264, 429496729, 421156193, 413283420, 405836262, 398777702, + 392075078, 385699449, 379625062, 373828919, 368290407, 362990988, + 357913941, 353044136, 348367849, 343872591, 339546978, 335380599, + 331363920, 327488186, 323745341, 320127961, 316629189, 313242684, + 309962565, 306783378, 303700049, 300707858, 297802400, 294979564, + 292235509, 289566636, 286969573, 284441157, 281978417, 279578557, + 277238946, 274957105, 272730696, 270557508, 268435456 }; +#endif + +# ifdef ENABLE_HR_MODE +RAM_ALIGN const Word16 adjust_global_gain_tables[5][NUM_SAMP_FREQ] = {{80, 230, 380, 530, 680, 830}, + {500, 1025, 1550, 2075, 2600, 3125}, + {850, 1700, 2550, 3400, 4250, 5100}, + {189, 164, 155, 151, 148, 146}, + {1310, 3241, 5268, 7326, 9400, 11482}}; +# else +RAM_ALIGN const Word16 adjust_global_gain_tables[5][NUM_SAMP_FREQ] = {{80, 230, 380, 530, 680}, + {500, 1025, 1550, 2075, 2600}, + {850, 1700, 2550, 3400, 4250}, + {189, 164, 155, 151, 148}, + {1310, 3241, 5268, 7326, 9400}}; +# endif + +#if defined(CR8_A_PLC_FADEOUT_TUNING) +const Word16 plc_fadeout_param_maxlen[4] = {800, 400, 266, 200}; +const Word16 plc_fadeout_param_maxbytes[4] = {27, 14, 9, 7}; +#endif diff --git a/lib_lc3plus/constants.h b/lib_lc3plus/constants.h new file mode 100644 index 000000000..8dee7e6eb --- /dev/null +++ b/lib_lc3plus/constants.h @@ -0,0 +1,402 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include "defines.h" + +#include "basop_util_lc3plus.h" + + +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 BW_cutoff_bin_all_HR[]; + +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA_2_5ms[2]; +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA_5ms[2]; +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA_7_5ms[2]; +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_HRA[2]; +#endif + +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len[6]; +# else +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len[5]; +# endif +extern RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes[NUM_SAMP_FREQ]; +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960[6]; +# else +extern RAM_ALIGN const Word16 *const LowDelayShapes_n960[6]; +# endif + +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_5ms[6]; +# else +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_5ms[5]; +# endif +extern RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes_5ms[NUM_SAMP_FREQ]; +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_5ms[6]; +# else +extern RAM_ALIGN const Word16 *const LowDelayShapes_n960_5ms[6]; +# endif +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_2_5ms[6]; +#else +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_2_5ms[5]; +#endif +extern RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes_2_5ms[NUM_SAMP_FREQ]; +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_2_5ms[6]; +# else +extern RAM_ALIGN const Word16 *const LowDelayShapes_n960_2_5ms[6]; +# endif + +# ifdef CR8_G_ADD_75MS +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 *const LowDelayShapes_n960_7_5ms[5]; +# else +extern RAM_ALIGN const Word16 *const LowDelayShapes_n960_7_5ms[5]; +# endif + +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_7_5ms[6]; +# else +extern RAM_ALIGN const Word16 LowDelayShapes_n960_len_7_5ms[5]; +# endif +extern RAM_ALIGN const Word16 LowDelayShapes_n960_la_zeroes_7_5ms[NUM_SAMP_FREQ]; +# endif + +extern RAM_ALIGN const Word16 NN_thresh; +extern RAM_ALIGN const Word16 NN_thresh_exp; +#ifdef CR8_E_TONE_DETECTOR +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 TD_HR_thresh_10ms; +# ifdef ENABLE_075_DMS_MODE +extern RAM_ALIGN const Word32 TD_HR_thresh_7_5ms; +# endif +extern RAM_ALIGN const Word32 TD_HR_thresh_5ms; +extern RAM_ALIGN const Word32 TD_HR_thresh_2_5ms; +# endif /* ENABLE_HR_MODE */ +#endif /* CR8_E_TONE_DETECTOR */ +extern RAM_ALIGN const Word32 BW_thresh_quiet[4]; +extern RAM_ALIGN const Word16 BW_thresh_quiet_exp; +extern RAM_ALIGN const Word16 BW_thresh_brickwall[4]; + +extern RAM_ALIGN const Word16 BW_cutoff_bin_all[]; +extern RAM_ALIGN const Word16 BW_cutoff_bits_all[]; + +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 bands_number_2_5ms_HR[]; +#endif + +extern RAM_ALIGN const Word16 BW_brickwall_dist[4]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_start_all[MAX_BW_BANDS_NUMBER - 1]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_stop_all[MAX_BW_BANDS_NUMBER - 1]; + +extern RAM_ALIGN const Word16 BW_brickwall_dist_5ms[4]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_start_all_5ms[MAX_BW_BANDS_NUMBER - 1]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_stop_all_5ms[MAX_BW_BANDS_NUMBER - 1]; +extern RAM_ALIGN const Word16 BW_brickwall_dist_2_5ms[4]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_start_all_2_5ms[MAX_BW_BANDS_NUMBER - 1]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_stop_all_2_5ms[MAX_BW_BANDS_NUMBER - 1]; + +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_075_DMS_MODE +extern RAM_ALIGN const Word16 BW_brickwall_dist_7_5ms[4]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_start_all_7_5ms[]; +extern RAM_ALIGN const Word16 *const BW_warp_idx_stop_all_7_5ms[]; +# endif +#endif + +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq[MAX_BW_BANDS_NUMBER]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq[MAX_BW_BANDS_NUMBER]; + +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq_HR[2]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_HR[2]; + +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq_5ms_HR[2]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_5ms_HR[2]; + +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq_2_5ms_HR[2]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_2_5ms_HR[2]; +# endif + +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq_5ms[MAX_BW_BANDS_NUMBER]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_5ms[MAX_BW_BANDS_NUMBER]; + + +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq_2_5ms[MAX_BW_BANDS_NUMBER]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_2_5ms[MAX_BW_BANDS_NUMBER]; + +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_075_DMS_MODE +extern RAM_ALIGN const Word16 *const tns_subdiv_startfreq_7_5ms[]; +extern RAM_ALIGN const Word16 *const tns_subdiv_stopfreq_7_5ms[]; +# endif +#endif + +extern RAM_ALIGN const Word16 Tab_esc_nb[4]; + +extern RAM_ALIGN const Word8 ari_spec_lookup[4096]; +extern RAM_ALIGN const UWord16 ari_spec_cumfreq[64][17]; +extern RAM_ALIGN const UWord16 ari_spec_freq[64][17]; +extern RAM_ALIGN const UWord16 ari_spec_bits[64][17]; + +extern RAM_ALIGN const Word32 tnsAcfWindow_lc3plus[MAXLAG]; +extern RAM_ALIGN const Word16 ac_tns_order_bits[2][MAXLAG]; +extern RAM_ALIGN const Word16 ac_tns_order_freq[2][MAXLAG]; +extern RAM_ALIGN const Word16 ac_tns_order_cumfreq[2][MAXLAG]; +extern RAM_ALIGN const Word16 ac_tns_coef_bits[MAXLAG][TNS_COEF_RES]; +extern RAM_ALIGN const Word16 ac_tns_coef_freq[MAXLAG][TNS_COEF_RES]; +extern RAM_ALIGN const Word16 ac_tns_coef_cumfreq[MAXLAG][TNS_COEF_RES]; +extern RAM_ALIGN const Word16 tnsQuantPts[TNS_COEF_RES]; +extern RAM_ALIGN const Word16 tnsQuantThr[TNS_COEF_RES - 1]; + +extern RAM_ALIGN const Word16 *const lpc_pre_emphasis[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_pre_emphasis_e[NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_2_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_2_5ms[NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 *const lpc_warp_dee_emphasis[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_warp_dee_emphasis_e[NUM_SAMP_FREQ]; + +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_075_DMS_MODE +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_7_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const lpc_lin_pre_emphasis_e_7_5ms[NUM_SAMP_FREQ]; +# endif +#endif + +extern RAM_ALIGN const Word16 bands_nrg_scale[32]; + +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 *const bands_offset_2_5ms_HR[2]; +extern RAM_ALIGN const Word16 *const bands_offset_5ms_HR[2]; +extern RAM_ALIGN const Word16 *const bands_offset_HR[2]; +# endif + +extern RAM_ALIGN const Word16 *const bands_offset[6]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max[NUM_OFFSETS]; + +extern RAM_ALIGN const Word16 bands_number_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const bands_offset_5ms[6]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_5ms[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_5ms[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 bands_number_2_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const bands_offset_2_5ms[6]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_2_5ms[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_2_5ms[NUM_OFFSETS]; + +#ifdef CR8_G_ADD_75MS +#ifdef ENABLE_075_DMS_MODE +extern RAM_ALIGN const Word16 bands_number_7_5ms[]; +# ifndef GENERATE_BAND_TABLES +extern RAM_ALIGN const Word16 *const bands_offset_7_5ms[5]; +# endif +# ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word16 bands_number_7_5ms_HR[]; +# ifndef GENERATE_BAND_TABLES +extern RAM_ALIGN const Word16 *const bands_offset_7_5ms_HR[2]; +# endif +# endif +#endif +#endif + +extern RAM_ALIGN const Word16 pitch_max[5]; +extern RAM_ALIGN const Word16 plc_preemph_fac[NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 TDC_high_16[11]; +extern RAM_ALIGN const Word16 TDC_high_32[11]; +extern RAM_ALIGN const Word16 TDC_high_16_harm[11]; +extern RAM_ALIGN const Word16 TDC_high_32_harm[11]; + +extern RAM_ALIGN const Word32 *const lag_win[NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 *const bands_offset_lin[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_lin[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_lin[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const bands_offset_lin_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_lin_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_lin_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 *const bands_offset_lin_2_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_lin_2_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_lin_2_5ms[NUM_SAMP_FREQ]; + +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_075_DMS_MODE +extern RAM_ALIGN const Word16 bands_offset_with_one_max_7_5ms[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_7_5ms[NUM_OFFSETS]; +extern RAM_ALIGN const Word16 *const bands_offset_lin_7_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_one_max_lin_7_5ms[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 bands_offset_with_two_max_lin_7_5ms[NUM_SAMP_FREQ]; +# endif +#endif + +extern RAM_ALIGN const Word32 inv_odft_twiddle_80_re[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_80_im[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_60_re[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_60_im[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_40_re[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_40_im[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_20_re[M]; +extern RAM_ALIGN const Word32 inv_odft_twiddle_20_im[M]; + +#ifdef SUBSET_WB +extern RAM_ALIGN const Word16 resamp_filt_16k[240]; +#else +extern RAM_ALIGN const Word16 resamp_filt_16k[1]; +#endif +#ifdef SUBSET_SSWB +extern RAM_ALIGN const Word16 resamp_filt_24k[240]; +#else +extern RAM_ALIGN const Word16 resamp_filt_24k[1]; +#endif +#ifdef SUBSET_SWB +extern RAM_ALIGN const Word16 resamp_filt_32k[240]; +#else +extern RAM_ALIGN const Word16 resamp_filt_32k[1]; +#endif +#ifdef SUBSET_FB +extern RAM_ALIGN const Word16 resamp_filt_48k[240]; +#else +extern RAM_ALIGN const Word16 resamp_filt_48k[1]; +#endif + +extern RAM_ALIGN const Word16 resamp_params[NUM_SAMP_FREQ][4]; +extern RAM_ALIGN const Word16 *const resamp_filts[NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 highpass50_filt_num[3]; +extern RAM_ALIGN const Word16 highpass50_filt_den[2]; + +extern RAM_ALIGN const Word16 olpa_ac_weighting[98]; + +extern RAM_ALIGN const Word16 ltpf_ac_interp_filt[7][9]; +extern RAM_ALIGN const Word16 inter_filter[5][4][12]; +extern RAM_ALIGN const Word16 inter_filter_shift[5]; +extern RAM_ALIGN const Word16 inter_filter_len[5]; +extern RAM_ALIGN const Word16 tilt_filter[5][4][11]; +extern RAM_ALIGN const Word16 tilt_filter_len[5]; +extern RAM_ALIGN const Word16 gain_scale_fac[4]; +extern RAM_ALIGN const UWord16 pitch_scale[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 ltpf_overlap_len[NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 sns_vq_reg_adj_scf[2]; +extern RAM_ALIGN const Word16 sns_vq_reg_lf_adj_scf[4]; +extern RAM_ALIGN const Word16 sns_vq_near_adj_scf[4]; +extern RAM_ALIGN const Word16 sns_vq_far_adj_scf[8]; +extern RAM_ALIGN const Word16 *const sns_gaintabPtr[4]; +extern RAM_ALIGN const Word16 sns_gainSz[4]; +extern RAM_ALIGN const Word16 sns_gainMSBbits[4]; +extern RAM_ALIGN const Word16 sns_gainLSBbits[4]; +extern RAM_ALIGN const Word16 sns_Kval[4][2]; +extern RAM_ALIGN const UWord32 sns_MPVQ_Sz[4][2]; + +extern RAM_ALIGN const Word16 st1SCF0_7_base5_32x8_Q11[256]; +extern RAM_ALIGN const Word16 st1SCF8_15_base5_32x8_Q11[256]; + +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 st1SCF0_7_base5_32x8_Q27[256]; +extern RAM_ALIGN const Word32 st1SCF8_15_base5_32x8_Q27[256]; +#endif + +/* PVQ deindexing tables */ +extern RAM_ALIGN const UWord32 h_memN16K12[12 + 2]; +extern RAM_ALIGN const UWord32 h_memN10K22[22 + 2]; +extern RAM_ALIGN const UWord32 h_memN6K2[2 + 2]; +extern RAM_ALIGN const Word16 tabledKMAX[16 + 1]; +extern RAM_ALIGN const UWord32 *const MPVQ_offs_ptr[16 + 1]; + +extern RAM_ALIGN const Word16 isqrt_Q16tab[1 + SQRT_EN_MAX_FX]; +#ifdef ENABLE_HR_MODE +extern RAM_ALIGN const Word32 isqrt_Q31tab[1 + SQRT_EN_MAX_FX]; +#endif + +extern RAM_ALIGN const Word16 adjust_global_gain_tables[5][NUM_SAMP_FREQ]; + +extern RAM_ALIGN const Word16 sqrt_table_phecu[]; +extern RAM_ALIGN const Word16 POW_ATT_TABLE0[]; +extern RAM_ALIGN const Word16 POW_ATT_TABLE1[]; +#ifdef PLC2_FADEOUT_IN_MS +#if PLC2_FADEOUT_IN_MS == 0 +extern RAM_ALIGN const Word16 *const POW_ATT_TABLES[3]; +#else +#ifdef CR8_A_PLC_FADEOUT_TUNING +extern RAM_ALIGN const Word16 fade_scheme_tab_fx[24 / 2][3]; +extern RAM_ALIGN const Word16 *const POW_ATT_TABLES[1+24/2]; +#else +extern RAM_ALIGN const Word16 *const POW_ATT_TABLES[11]; +#endif + +#endif +#else +extern RAM_ALIGN const Word16 *const POW_ATT_TABLES[3]; +#endif + +#ifdef CR8_A_PLC_FADEOUT_TUNING +extern RAM_ALIGN const Word16 scATHFx[7]; +#endif + +extern RAM_ALIGN const Word16 e_tot_headroom[]; +extern RAM_ALIGN const Word16 xfp_wE_MDCT2FFTQ11[]; + +extern RAM_ALIGN const Word16 num_FsByResQ0[5]; +extern RAM_ALIGN const Word16 *const LprotSzPtr; +extern RAM_ALIGN const Word16 InvLprot_Q22[5]; +extern RAM_ALIGN const Word16 PhEcuFftScale[5]; +extern RAM_ALIGN const Word16 oneOverFrameQ15Tab[5]; +extern RAM_ALIGN const Word16 PhEcu_Xsav_Flt2FxDnShift[]; +extern RAM_ALIGN const Word16 PhEcu_Xsav_Flt2FxScaleQ15[]; +extern RAM_ALIGN const Word16 PhEcu_frac_thr_rise_lin_Q15[]; +extern RAM_ALIGN const Word16 PhEcu_frac_thr_decay_lin_Q15[]; + +extern RAM_ALIGN const Word16 mdct_grp_bins_fx[]; +extern RAM_ALIGN const Word16 xavg_N_grp_fx[]; +extern RAM_ALIGN const Word16 spec_shape_headroom[]; +extern RAM_ALIGN const Word16 rectLengthTab[NUM_SAMP_FREQ]; +extern RAM_ALIGN const Word16 hamm_len2Tab[]; + +#ifndef CR10_A_ATTENUATION_CURVE_SELECTOR +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH +extern RAM_ALIGN const Word16 FADE_OUT_TYPE_2_ALPHA_5MS[30]; +extern RAM_ALIGN const Word16 FADE_OUT_TYPE_2_ALPHA_2_5MS[60]; +#endif +#endif +extern RAM_ALIGN const Word16 gw_len_inv_shift_fx[]; +extern RAM_ALIGN const Word16 gwlpr_fx[]; + +extern RAM_ALIGN const Word16 sin_quarterQ15_fx[]; +extern RAM_ALIGN const Word16 sincos_lowres_tab_sinQ15_fx[]; + +extern RAM_ALIGN const Word16 *const PhECU_wins[5][3]; + +extern RAM_ALIGN const Word16 *const w_new[]; +extern RAM_ALIGN const Word16 *const w_old[]; + +/* extern RAM_ALIGN const Word16 WORK_LEN[]; */ +extern RAM_ALIGN const Word16 COPY_LEN[]; +extern RAM_ALIGN const Word16 OLA_LEN[]; + +#if defined(CR8_A_PLC_FADEOUT_TUNING) +extern const Word16 plc_fadeout_param_maxlen[4]; +extern const Word16 plc_fadeout_param_maxbytes[4]; +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR +extern RAM_ALIGN const Word16 PLC_FADEOUT_TYPE_2_SELECTOR; +#endif + +#endif /* CONSTANTS_H */ diff --git a/lib_lc3plus/cutoff_bandwidth.c b/lib_lc3plus/cutoff_bandwidth.c new file mode 100644 index 000000000..05f7cce49 --- /dev/null +++ b/lib_lc3plus/cutoff_bandwidth.c @@ -0,0 +1,26 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void process_cutoff_bandwidth(Word32 d_fx[], Word16 len, Word16 bw_bin) +{ + Counter i = 0; + if (len > bw_bin){ + /* roll off */ + for (i = -1; i < 3; i++) { + d_fx[bw_bin + i] = L_shr(d_fx[bw_bin + i], add(i, 2)); + } + + for (i = bw_bin + 3; i < len; i++) { + d_fx[i] = 0; move32(); + } + } +} + diff --git a/lib_lc3plus/dct2_fx.c b/lib_lc3plus/dct2_fx.c new file mode 100644 index 000000000..c301c2aeb --- /dev/null +++ b/lib_lc3plus/dct2_fx.c @@ -0,0 +1,473 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void idct16_fx(const Word16 *in, Word16 *out) +{ + Dyn_Mem_Deluxe_In( + Word16 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15; + Word16 b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15; + ); + + a8 = add(mult_r(in[1], 1136), mult_r(in[15], -11529)); /* Sπ/32/√8 -S15π/32/√8 */ + a9 = add(mult_r(in[9], 8956), mult_r(in[7], -7350)); /* S9π/32/√8 -S7π/32/√8 */ + a10 = add(mult_r(in[5], 5461), mult_r(in[11], -10217)); /* S5π/32/√8 -S11π/32/√8 */ + a11 = add(mult_r(in[13], 11086), mult_r(in[3], -3363)); /* S13π/32/√8 -S3π/32/√8 */ + a12 = add(mult_r(in[3], 11086), mult_r(in[13], 3363)); /* C3π/32/√8 C13π/32/√8 */ + a13 = add(mult_r(in[11], 5461), mult_r(in[5], 10217)); /* C11π/32/√8 C5π/32/√8 */ + a14 = add(mult_r(in[7], 8956), mult_r(in[9], 7350)); /* C7π/32/√8 C9π/32/√8 */ + a15 = add(mult_r(in[15], 1136), mult_r(in[1], 11529)); /* C15π/32/√8 Cπ/32/√8 */ + + b4 = add(mult_r(in[2], 2260), mult_r(in[14], -11363)); /* Sπ/16/√8 -S7π/16/√8 */ + b5 = add(mult_r(in[10], 9633), mult_r(in[6], -6436)); /* S5π/16/√8 -S3π/16/√8 */ + b6 = add(mult_r(in[6], 9633), mult_r(in[10], 6436)); /* C3π/16/√8 C5π/16/√8 */ + b7 = add(mult_r(in[14], 2260), mult_r(in[2], 11363)); /* C7π/16/√8 Cπ/16/√8 */ + b8 = add(a9, a8); + b9 = sub(a8, a9); + b10 = sub(a11, a10); + b11 = add(a10, a11); + b12 = add(a13, a12); + b13 = sub(a12, a13); + b14 = sub(a15, a14); + b15 = add(a14, a15); + + a0 = add(mult_r(in[0], 8192), mult_r(in[8], 8192)); /* Cπ/4/√8 Cπ/4/√8 */ + a1 = add(mult_r(in[8], -8192), mult_r(in[0], 8192)); /* -Cπ/4/√8 Cπ/4/√8 */ + a2 = add(mult_r(in[4], 4433), mult_r(in[12], -10703)); /* Sπ/8/√8 -S3π/8/√8 */ + a3 = add(mult_r(in[12], 4433), mult_r(in[4], 10703)); /* C3π/8/√8 Cπ/8/√8 */ + a4 = add(b5, b4); + a5 = sub(b4, b5); + a6 = sub(b7, b6); + a7 = add(b6, b7); + a8 = b8; move16(); + a9 = add(mult_r(b9, -30274), mult_r(b14, 12540)); /* -Cπ/8 C3π/8 */ + a10 = add(mult_r(b10, -12540), mult_r(b13, -30274)); /* -Sπ/8 -S3π/8 */ + a11 = b11; move16(); + a12 = b12; move16(); + a13 = add(mult_r(b13, 12540), mult_r(b10, -30274)); /* C3π/8 -Cπ/8 */ + a14 = add(mult_r(b14, 30274), mult_r(b9, 12540)); /* S3π/8 Sπ/8 */ + a15 = b15; move16(); + + b0 = add(a3, a0); + b1 = add(a2, a1); + b2 = sub(a1, a2); + b3 = sub(a0, a3); + b4 = a4; move16(); + b5 = add(mult_r(a5, -23170), mult_r(a6, 23170)); /* -Cπ/4 Cπ/4 */ + b6 = add(mult_r(a6, 23170), mult_r(a5, 23170)); /* Cπ/4 Cπ/4 */ + b7 = a7; move16(); + b8 = add(a11, a8); + b9 = add(a10, a9); + b10 = sub(a9, a10); + b11 = sub(a8, a11); + b12 = sub(a15, a12); + b13 = sub(a14, a13); + b14 = add(a13, a14); + b15 = add(a12, a15); + + a0 = add(b7, b0); + a1 = add(b6, b1); + a2 = add(b5, b2); + a3 = add(b4, b3); + a4 = sub(b3, b4); + a5 = sub(b2, b5); + a6 = sub(b1, b6); + a7 = sub(b0, b7); + a10 = add(mult_r(b10, -23170), mult_r(b13, 23170)); /* -Cπ/4 Cπ/4 */ + a11 = add(mult_r(b11, -23170), mult_r(b12, 23170)); /* -Cπ/4 Cπ/4 */ + a12 = add(mult_r(b12, 23170), mult_r(b11, 23170)); /* Cπ/4 Cπ/4 */ + a13 = add(mult_r(b13, 23170), mult_r(b10, 23170)); /* Cπ/4 Cπ/4 */ + + out[0] = add(b15, a0); move16(); + out[1] = add(b14, a1); move16(); + out[2] = add(a13, a2); move16(); + out[3] = add(a12, a3); move16(); + out[4] = add(a11, a4); move16(); + out[5] = add(a10, a5); move16(); + out[6] = add(b9, a6); move16(); + out[7] = add(b8, a7); move16(); + out[8] = sub(a7, b8); move16(); + out[9] = sub(a6, b9); move16(); + out[10] = sub(a5, a10); move16(); + out[11] = sub(a4, a11); move16(); + out[12] = sub(a3, a12); move16(); + out[13] = sub(a2, a13); move16(); + out[14] = sub(a1, b14); move16(); + out[15] = sub(a0, b15); move16(); + + Dyn_Mem_Deluxe_Out(); +} + +void dct32_fx(const Word32 *in, Word32 *out) +{ + Dyn_Mem_Deluxe_In(Word32 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15; + Word32 b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;); + + a0 = L_add(in[15], in[0]); + a1 = L_add(in[14], in[1]); + a2 = L_add(in[13], in[2]); + a3 = L_add(in[12], in[3]); + a4 = L_add(in[11], in[4]); + a5 = L_add(in[10], in[5]); + a6 = L_add(in[9], in[6]); + a7 = L_add(in[8], in[7]); + a10 = L_sub(in[5], in[10]); + a11 = L_sub(in[4], in[11]); + a12 = L_sub(in[3], in[12]); + a13 = L_sub(in[2], in[13]); + + b0 = L_add(a7, a0); + b1 = L_add(a6, a1); + b2 = L_add(a5, a2); + b3 = L_add(a4, a3); + b4 = L_sub(a3, a4); +#ifdef CR9_C_FIX_DCT2_OVERFLOW + b5 = L_sub_sat(a2, a5); +#else + b5 = L_sub(a2, a5); +#endif +#ifdef CR9_C_FIX_DCT2_OVERFLOW + b6 = L_sub_sat(a1, a6); +#else + b6 = L_sub(a1, a6); +#endif + b7 = L_sub(a0, a7); + b8 = L_sub(in[7], in[8]); + b9 = L_sub(in[6], in[9]); + b10 = L_add(Mpy_32_16_lc3plus(a10, -23170), Mpy_32_16_lc3plus(a13, 23170)); /* -Cπ/4 Cπ/4 */ + b11 = L_add(Mpy_32_16_lc3plus(a11, -23170), Mpy_32_16_lc3plus(a12, 23170)); /* -Cπ/4 Cπ/4 */ + b12 = L_add(Mpy_32_16_lc3plus(a12, 23170), Mpy_32_16_lc3plus(a11, 23170)); /* Cπ/4 Cπ/4 */ + b13 = L_add(Mpy_32_16_lc3plus(a13, 23170), Mpy_32_16_lc3plus(a10, 23170)); /* Cπ/4 Cπ/4 */ + b14 = L_sub(in[1], in[14]); + b15 = L_sub(in[0], in[15]); + + a0 = L_add(b3, b0); + a1 = L_add(b2, b1); + a2 = L_sub(b1, b2); + a3 = L_sub_sat(b0, b3); + a4 = b4; + move16(); + a5 = L_add(Mpy_32_16_lc3plus(b5, -23170), Mpy_32_16_lc3plus(b6, 23170)); /* -Cπ/4 Cπ/4 */ + a6 = L_add(Mpy_32_16_lc3plus(b6, 23170), Mpy_32_16_lc3plus(b5, 23170)); /* Cπ/4 Cπ/4 */ + a7 = b7; + move16(); + a8 = L_add(b11, b8); + a9 = L_add(b10, b9); + a10 = L_sub(b9, b10); + a11 = L_sub(b8, b11); + a12 = L_sub(b15, b12); + a13 = L_sub(b14, b13); + a14 = L_add(b13, b14); + a15 = L_add(b12, b15); + + out[0] = L_add(Mpy_32_16_lc3plus(a0, 8192), Mpy_32_16_lc3plus(a1, 8192)); + move16(); /* Cπ/4/√8 Cπ/4/√8 */ + out[8] = L_add(Mpy_32_16_lc3plus(a1, -8192), Mpy_32_16_lc3plus(a0, 8192)); + move16(); /* -Cπ/4/√8 Cπ/4/√8 */ + out[4] = L_add(Mpy_32_16_lc3plus(a2, 4433), Mpy_32_16_lc3plus(a3, 10703)); + move16(); /* Sπ/8/√8 Cπ/8/√8 */ + out[12] = L_add(Mpy_32_16_lc3plus(a3, 4433), Mpy_32_16_lc3plus(a2, -10703)); + move16(); /* C3π/8/√8 -S3π/8/√8 */ + b4 = L_add(a5, a4); + b5 = L_sub(a4, a5); + b6 = L_sub_sat(a7, a6); + b7 = L_add(a6, a7); + b8 = a8; + move16(); + b9 = L_add(Mpy_32_16_lc3plus(a9, -30274), Mpy_32_16_lc3plus(a14, 12540)); /* -Cπ/8 Sπ/8 */ + b10 = L_add(Mpy_32_16_lc3plus(a10, -12540), Mpy_32_16_lc3plus(a13, -30274)); /* -Sπ/8 -Cπ/8 */ + b11 = a11; + move16(); + b12 = a12; + move16(); + b13 = L_add(Mpy_32_16_lc3plus(a13, 12540), Mpy_32_16_lc3plus(a10, -30274)); /* C3π/8 -S3π/8 */ + b14 = L_add(Mpy_32_16_lc3plus(a14, 30274), Mpy_32_16_lc3plus(a9, 12540)); /* S3π/8 C3π/8 */ + b15 = a15; + move16(); + + out[2] = L_add(Mpy_32_16_lc3plus(b4, 2260), Mpy_32_16_lc3plus(b7, 11363)); + move16(); /* Sπ/16/√8 Cπ/16/√8 */ + out[10] = L_add(Mpy_32_16_lc3plus(b5, 9633), Mpy_32_16_lc3plus(b6, 6436)); + move16(); /* S5π/16/√8 C5π/16/√8 */ + out[6] = L_add(Mpy_32_16_lc3plus(b6, 9633), Mpy_32_16_lc3plus(b5, -6436)); + move16(); /* C3π/16/√8 -S3π/16/√8 */ + out[14] = L_add(Mpy_32_16_lc3plus(b7, 2260), Mpy_32_16_lc3plus(b4, -11363)); + move16(); /* C7π/16/√8 -S7π/16/√8 */ + + a8 = L_add_sat(b9, b8); + a9 = L_sub_sat(b8, b9); + a10 = L_sub_sat(b11, b10); + a11 = L_add_sat(b10, b11); + a12 = L_add_sat(b13, b12); + a13 = L_sub_sat(b12, b13); + a14 = L_sub_sat(b15, b14); + a15 = L_add_sat(b14, b15); + + out[1] = L_add(Mpy_32_16_lc3plus(a8, 1136), Mpy_32_16_lc3plus(a15, 11529)); + move16(); /* Sπ/32/√8 Cπ/32/√8 */ + out[9] = L_add(Mpy_32_16_lc3plus(a9, 8956), Mpy_32_16_lc3plus(a14, 7350)); + move16(); /* S9π/32/√8 C9π/32/√8 */ + out[5] = L_add(Mpy_32_16_lc3plus(a10, 5461), Mpy_32_16_lc3plus(a13, 10217)); + move16(); /* S5π/32/√8 C5π/32/√8 */ + out[13] = L_add(Mpy_32_16_lc3plus(a11, 11086), Mpy_32_16_lc3plus(a12, 3363)); + move16(); /* S13π/32/√8 C13π/32/√8 */ + out[3] = L_add(Mpy_32_16_lc3plus(a12, 11086), Mpy_32_16_lc3plus(a11, -3363)); + move16(); /* C3π/32/√8 -S3π/32/√8 */ + out[11] = L_add(Mpy_32_16_lc3plus(a13, 5461), Mpy_32_16_lc3plus(a10, -10217)); + move16(); /* C11π/32/√8 -S11π/32/√8 */ + out[7] = L_add(Mpy_32_16_lc3plus(a14, 8956), Mpy_32_16_lc3plus(a9, -7350)); + move16(); /* C7π/32/√8 -S7π/32/√8 */ + out[15] = L_add(Mpy_32_16_lc3plus(a15, 1136), Mpy_32_16_lc3plus(a8, -11529)); + move16(); /* C15π/32/√8 -S15/32/√8 */ + + Dyn_Mem_Deluxe_Out(); +} + +void idct32_fx(const Word32 *in, Word32 *out) +{ + Dyn_Mem_Deluxe_In(Word32 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15; + Word32 b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;); + + a8 = L_add(Mpy_32_16_lc3plus(in[1], 1136), Mpy_32_16_lc3plus(in[15], -11529)); /* Sπ/32/√8 -S15π/32/√8 */ + a9 = L_add(Mpy_32_16_lc3plus(in[9], 8956), Mpy_32_16_lc3plus(in[7], -7350)); /* S9π/32/√8 -S7π/32/√8 */ + a10 = L_add(Mpy_32_16_lc3plus(in[5], 5461), Mpy_32_16_lc3plus(in[11], -10217)); /* S5π/32/√8 -S11π/32/√8 */ + a11 = L_add(Mpy_32_16_lc3plus(in[13], 11086), Mpy_32_16_lc3plus(in[3], -3363)); /* S13π/32/√8 -S3π/32/√8 */ + a12 = L_add(Mpy_32_16_lc3plus(in[3], 11086), Mpy_32_16_lc3plus(in[13], 3363)); /* C3π/32/√8 C13π/32/√8 */ + a13 = L_add(Mpy_32_16_lc3plus(in[11], 5461), Mpy_32_16_lc3plus(in[5], 10217)); /* C11π/32/√8 C5π/32/√8 */ + a14 = L_add(Mpy_32_16_lc3plus(in[7], 8956), Mpy_32_16_lc3plus(in[9], 7350)); /* C7π/32/√8 C9π/32/√8 */ + a15 = L_add(Mpy_32_16_lc3plus(in[15], 1136), Mpy_32_16_lc3plus(in[1], 11529)); /* C15π/32/√8 Cπ/32/√8 */ + + b4 = L_add(Mpy_32_16_lc3plus(in[2], 2260), Mpy_32_16_lc3plus(in[14], -11363)); /* Sπ/16/√8 -S7π/16/√8 */ + b5 = L_add(Mpy_32_16_lc3plus(in[10], 9633), Mpy_32_16_lc3plus(in[6], -6436)); /* S5π/16/√8 -S3π/16/√8 */ + b6 = L_add(Mpy_32_16_lc3plus(in[6], 9633), Mpy_32_16_lc3plus(in[10], 6436)); /* C3π/16/√8 C5π/16/√8 */ + b7 = L_add(Mpy_32_16_lc3plus(in[14], 2260), Mpy_32_16_lc3plus(in[2], 11363)); /* C7π/16/√8 Cπ/16/√8 */ + b8 = L_add(a9, a8); + b9 = L_sub(a8, a9); + b10 = L_sub(a11, a10); + b11 = L_add(a10, a11); + b12 = L_add(a13, a12); + b13 = L_sub(a12, a13); + b14 = L_sub(a15, a14); + b15 = L_add(a14, a15); + + a0 = L_add(Mpy_32_16_lc3plus(in[0], 8192), Mpy_32_16_lc3plus(in[8], 8192)); /* Cπ/4/√8 Cπ/4/√8 */ + a1 = L_add(Mpy_32_16_lc3plus(in[8], -8192), Mpy_32_16_lc3plus(in[0], 8192)); /* -Cπ/4/√8 Cπ/4/√8 */ + a2 = L_add(Mpy_32_16_lc3plus(in[4], 4433), Mpy_32_16_lc3plus(in[12], -10703)); /* Sπ/8/√8 -S3π/8/√8 */ + a3 = L_add(Mpy_32_16_lc3plus(in[12], 4433), Mpy_32_16_lc3plus(in[4], 10703)); /* C3π/8/√8 Cπ/8/√8 */ + a4 = L_add(b5, b4); + a5 = L_sub(b4, b5); + a6 = L_sub(b7, b6); + a7 = L_add(b6, b7); + a8 = b8; + move32(); + a9 = L_add(Mpy_32_16_lc3plus(b9, -30274), Mpy_32_16_lc3plus(b14, 12540)); /* -Cπ/8 C3π/8 */ + a10 = L_add(Mpy_32_16_lc3plus(b10, -12540), Mpy_32_16_lc3plus(b13, -30274)); /* -Sπ/8 -S3π/8 */ + a11 = b11; + move32(); + a12 = b12; + move32(); + a13 = L_add(Mpy_32_16_lc3plus(b13, 12540), Mpy_32_16_lc3plus(b10, -30274)); /* C3π/8 -Cπ/8 */ + a14 = L_add(Mpy_32_16_lc3plus(b14, 30274), Mpy_32_16_lc3plus(b9, 12540)); /* S3π/8 Sπ/8 */ + a15 = b15; + move32(); + + b0 = L_add(a3, a0); + b1 = L_add(a2, a1); + b2 = L_sub(a1, a2); + b3 = L_sub(a0, a3); + b4 = a4; + move32(); + b5 = L_add(Mpy_32_16_lc3plus(a5, -23170), Mpy_32_16_lc3plus(a6, 23170)); /* -Cπ/4 Cπ/4 */ + b6 = L_add(Mpy_32_16_lc3plus(a6, 23170), Mpy_32_16_lc3plus(a5, 23170)); /* Cπ/4 Cπ/4 */ + b7 = a7; + move32(); + b8 = L_add(a11, a8); + b9 = L_add(a10, a9); + b10 = L_sub(a9, a10); + b11 = L_sub(a8, a11); + b12 = L_sub(a15, a12); + b13 = L_sub(a14, a13); + b14 = L_add(a13, a14); + b15 = L_add(a12, a15); + + a0 = L_add(b7, b0); + a1 = L_add(b6, b1); + a2 = L_add(b5, b2); + a3 = L_add(b4, b3); + a4 = L_sub(b3, b4); + a5 = L_sub(b2, b5); + a6 = L_sub(b1, b6); + a7 = L_sub(b0, b7); + a10 = L_add(Mpy_32_16_lc3plus(b10, -23170), Mpy_32_16_lc3plus(b13, 23170)); /* -Cπ/4 Cπ/4 */ + a11 = L_add(Mpy_32_16_lc3plus(b11, -23170), Mpy_32_16_lc3plus(b12, 23170)); /* -Cπ/4 Cπ/4 */ + a12 = L_add(Mpy_32_16_lc3plus(b12, 23170), Mpy_32_16_lc3plus(b11, 23170)); /* Cπ/4 Cπ/4 */ + a13 = L_add(Mpy_32_16_lc3plus(b13, 23170), Mpy_32_16_lc3plus(b10, 23170)); /* Cπ/4 Cπ/4 */ + + out[0] = L_add(b15, a0); + move32(); + out[1] = L_add(b14, a1); + move32(); + out[2] = L_add(a13, a2); + move32(); + out[3] = L_add(a12, a3); + move32(); + out[4] = L_add(a11, a4); + move32(); + out[5] = L_add(a10, a5); + move32(); + out[6] = L_add(b9, a6); + move32(); + out[7] = L_add(b8, a7); + move32(); + out[8] = L_sub(a7, b8); + move32(); + out[9] = L_sub(a6, b9); + move32(); + out[10] = L_sub(a5, a10); + move32(); + out[11] = L_sub(a4, a11); + move32(); + out[12] = L_sub(a3, a12); + move32(); + out[13] = L_sub(a2, a13); + move32(); + out[14] = L_sub(a1, b14); + move32(); + out[15] = L_sub(a0, b15); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +void idct32_32_fx(const Word32 *in, Word32 *out) +{ + Dyn_Mem_Deluxe_In(Word32 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15; + Word32 b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;); + + /*round(sin(pi*(1:16)/32)/sqrt(8)*2^31) = + 74419526 148122351 220398677 290552444 357908031 421816769 481663180 536870912 + 586908283 631293407 669598830 701455651 726557070 744661347 755594128 759250125 + */ + /*ound(cos(pi*(1:16)/32)/sqrt(8)*2^31) = + 755594128 744661347 726557070 701455651 669598830 631293407 586908283 536870912 + 481663180 421816769 357908031 290552444 220398677 148122351 74419526 0 + */ + + a8 = L_add(Mpy_32_32_lc3plus(in[1], 74419526), Mpy_32_32_lc3plus(in[15], -755594128)); /* Sπ/32/√8 -S15π/32/√8 */ + a9 = L_add(Mpy_32_32_lc3plus(in[9], 586908283), Mpy_32_32_lc3plus(in[7], -481663180)); /* S9π/32/√8 -S7π/32/√8 */ + a10 = L_add(Mpy_32_32_lc3plus(in[5], 357908031), Mpy_32_32_lc3plus(in[11], -669598830)); /* S5π/32/√8 -S11π/32/√8 */ + a11 = L_add(Mpy_32_32_lc3plus(in[13], 726557070), Mpy_32_32_lc3plus(in[3], -220398677)); /* S13π/32/√8 -S3π/32/√8 */ + + a12 = L_add(Mpy_32_32_lc3plus(in[3], 726557070), Mpy_32_32_lc3plus(in[13], 220398677)); /* C3π/32/√8 C13π/32/√8 */ + a13 = L_add(Mpy_32_32_lc3plus(in[11], 357908031), Mpy_32_32_lc3plus(in[5], 669598830)); /* C11π/32/√8 C5π/32/√8 */ + a14 = L_add(Mpy_32_32_lc3plus(in[7], 586908283), Mpy_32_32_lc3plus(in[9], 481663180)); /* C7π/32/√8 C9π/32/√8 */ + a15 = L_add(Mpy_32_32_lc3plus(in[15], 74419526), Mpy_32_32_lc3plus(in[1], 755594128)); /* C15π/32/√8 Cπ/32/√8 */ + + b4 = L_add(Mpy_32_32_lc3plus(in[2], 148122351), Mpy_32_32_lc3plus(in[14], -744661347)); /* Sπ/16/√8 -S7π/16/√8 */ + b5 = L_add(Mpy_32_32_lc3plus(in[10], 631293407), Mpy_32_32_lc3plus(in[6], -421816769)); /* S5π/16/√8 -S3π/16/√8 */ + b6 = L_add(Mpy_32_32_lc3plus(in[6], 631293407), Mpy_32_32_lc3plus(in[10], 421816769)); /* C3π/16/√8 C5π/16/√8 */ + b7 = L_add(Mpy_32_32_lc3plus(in[14], 148122351), Mpy_32_32_lc3plus(in[2], 744661347)); /* C7π/16/√8 Cπ/16/√8 */ + b8 = L_add(a9, a8); + b9 = L_sub(a8, a9); + b10 = L_sub(a11, a10); + b11 = L_add(a10, a11); + b12 = L_add(a13, a12); + b13 = L_sub(a12, a13); + b14 = L_sub(a15, a14); + b15 = L_add(a14, a15); + + a0 = L_add(Mpy_32_32_lc3plus(in[0], 536870912), Mpy_32_32_lc3plus(in[8], 536870912)); /* Cπ/4/√8 Cπ/4/√8 */ + a1 = L_add(Mpy_32_32_lc3plus(in[8], -536870912), Mpy_32_32_lc3plus(in[0], 536870912)); /* -Cπ/4/√8 Cπ/4/√8 */ + a2 = L_add(Mpy_32_32_lc3plus(in[4], 290552444), Mpy_32_32_lc3plus(in[12], -701455651)); /* Sπ/8/√8 -S3π/8/√8 */ + a3 = L_add(Mpy_32_32_lc3plus(in[12], 290552444), Mpy_32_32_lc3plus(in[4], 701455651)); /* C3π/8/√8 Cπ/8/√8 */ + a4 = L_add(b5, b4); + a5 = L_sub(b4, b5); + a6 = L_sub(b7, b6); + a7 = L_add(b6, b7); + a8 = b8; + move32(); + a9 = L_add(Mpy_32_32_lc3plus(b9, -1984016189), Mpy_32_32_lc3plus(b14, 821806413)); /* -Cπ/8 C3π/8 */ + a10 = L_add(Mpy_32_32_lc3plus(b10, -821806413), Mpy_32_32_lc3plus(b13, -1984016189)); /* -Sπ/8 -S3π/8 */ + a11 = b11; + move32(); + a12 = b12; + move32(); + a13 = L_add(Mpy_32_32_lc3plus(b13, 821806413), Mpy_32_32_lc3plus(b10, -1984016189)); /* C3π/8 -Cπ/8 */ + a14 = L_add(Mpy_32_32_lc3plus(b14, 1984016189), Mpy_32_32_lc3plus(b9, 821806413)); /* S3π/8 Sπ/8 */ + a15 = b15; + move32(); + + b0 = L_add(a3, a0); + b1 = L_add(a2, a1); + b2 = L_sub(a1, a2); + b3 = L_sub(a0, a3); + b4 = a4; + move32(); + b5 = L_add(Mpy_32_32_lc3plus(a5, -1518500250), Mpy_32_32_lc3plus(a6, 1518500250)); /* -Cπ/4 Cπ/4 */ + b6 = L_add(Mpy_32_32_lc3plus(a6, 1518500250), Mpy_32_32_lc3plus(a5, 1518500250)); /* Cπ/4 Cπ/4 */ + b7 = a7; + move32(); + b8 = L_add(a11, a8); + b9 = L_add(a10, a9); + b10 = L_sub(a9, a10); + b11 = L_sub(a8, a11); + b12 = L_sub(a15, a12); + b13 = L_sub(a14, a13); + b14 = L_add(a13, a14); + b15 = L_add(a12, a15); + + a0 = L_add(b7, b0); + a1 = L_add(b6, b1); + a2 = L_add(b5, b2); + a3 = L_add(b4, b3); + a4 = L_sub(b3, b4); + a5 = L_sub(b2, b5); + a6 = L_sub(b1, b6); + a7 = L_sub(b0, b7); + a10 = L_add(Mpy_32_32_lc3plus(b10, -1518500250), Mpy_32_32_lc3plus(b13, 1518500250)); /* -Cπ/4 Cπ/4 */ + a11 = L_add(Mpy_32_32_lc3plus(b11, -1518500250), Mpy_32_32_lc3plus(b12, 1518500250)); /* -Cπ/4 Cπ/4 */ + a12 = L_add(Mpy_32_32_lc3plus(b12, 1518500250), Mpy_32_32_lc3plus(b11, 1518500250)); /* Cπ/4 Cπ/4 */ + a13 = L_add(Mpy_32_32_lc3plus(b13, 1518500250), Mpy_32_32_lc3plus(b10, 1518500250)); /* Cπ/4 Cπ/4 */ + + out[0] = L_add(b15, a0); + move32(); + out[1] = L_add(b14, a1); + move32(); + out[2] = L_add(a13, a2); + move32(); + out[3] = L_add(a12, a3); + move32(); + out[4] = L_add(a11, a4); + move32(); + out[5] = L_add(a10, a5); + move32(); + out[6] = L_add(b9, a6); + move32(); + out[7] = L_add(b8, a7); + move32(); + out[8] = L_sub(a7, b8); + move32(); + out[9] = L_sub(a6, b9); + move32(); + out[10] = L_sub(a5, a10); + move32(); + out[11] = L_sub(a4, a11); + move32(); + out[12] = L_sub(a3, a12); + move32(); + out[13] = L_sub(a2, a13); + move32(); + out[14] = L_sub(a1, b14); + move32(); + out[15] = L_sub(a0, b15); + move32(); + + Dyn_Mem_Deluxe_Out(); +} diff --git a/lib_lc3plus/dct4_fx.c b/lib_lc3plus/dct4_fx.c new file mode 100644 index 000000000..af98a395d --- /dev/null +++ b/lib_lc3plus/dct4_fx.c @@ -0,0 +1,228 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include "rom_basop_util.h" + + +void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ + Word16 *pDat_e, /* i/o: pointer to data exponent */ + Word16 L, /* i : length of block */ +#ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION +# ifdef ENABLE_HR_MODE + Word16 hrmode, /* indicate high precision usage */ +# endif +#endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + Word32 *workBuffer) /* : size of L */ + +{ + Word16 sin_step; + Word16 idx; + Word16 M_var; + Word16 M2; + + Word32 *pDat_0; + Word32 *pDat_1; + + Word32 accu1; + Word32 accu2; + Word32 accu3; + Word32 accu4; + + Counter i; + +#ifdef ENABLE_HR_MODE + const PWord32 *twiddle; + const PWord32 *sin_twiddle; +#else + const PWord16 *twiddle; + const PWord16 *sin_twiddle; +#endif + +#ifdef ENABLE_DCTIV_RESCALE + Word16 scale; +#endif + +#ifdef DYNMEM_COUNT +#ifdef ENABLE_HR_MODE + Dyn_Mem_In("dct_IV", sizeof(struct { + Word16 sin_step; + Word16 idx; + Counter i; + Word16 M_var; + Word16 M2; + + Word32 *pDat_0; + Word32 *pDat_1; + + Word32 accu1; + Word32 accu2; + Word32 accu3; + Word32 accu4; + + const PWord32 *twiddle; + const PWord32 *sin_twiddle; + })); + +#else + Dyn_Mem_In("dct_IV", sizeof(struct { + Word16 sin_step; + Word16 idx; + Counter i; + Word16 M_var; + Word16 M2; + + Word32 *pDat_0; + Word32 *pDat_1; + + Word32 accu1; + Word32 accu2; + Word32 accu3; + Word32 accu4; + + const PWord16 *twiddle; + const PWord16 *sin_twiddle; + })); +#endif /* ENABLE_HR_MODE */ +#endif /* DYNMEM_COUNT */ + + M_var = shr_pos_pos(L, 1); + M2 = sub(M_var, 1); + + BASOP_getTables(&twiddle, &sin_twiddle, &sin_step, L); + + pDat_0 = &pDat[0]; + pDat_1 = &pDat[L - 2]; + + FOR (i = 0; i < M2; i += 2) + { +#ifdef ENABLE_HR_MODE +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + if (hrmode) { + cplxMpy32_32_32_2(accu1, accu2, pDat_1[1], pDat_0[0], twiddle[i].v.re, twiddle[i].v.im); + cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_0[1], twiddle[i + 1].v.re, twiddle[i + 1].v.im); + } else { + cplxMpy32_32_16_2(accu1, accu2, pDat_1[1], pDat_0[0], round_fx_sat(twiddle[i].v.re), round_fx_sat(twiddle[i].v.im)); + cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_0[1], round_fx_sat(twiddle[i + 1].v.re), round_fx_sat(twiddle[i + 1].v.im)); + } +# else /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + cplxMpy32_32_32_2(accu1, accu2, pDat_1[1], pDat_0[0], twiddle[i].v.re, twiddle[i].v.im); + cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_0[1], twiddle[i + 1].v.re, twiddle[i + 1].v.im); +# endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + +#else + cplxMpy32_32_16_2(accu1, accu2, pDat_1[1], pDat_0[0], twiddle[i].v.re, twiddle[i].v.im); + cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_0[1], twiddle[i + 1].v.re, twiddle[i + 1].v.im); +#endif + + pDat_0[0] = accu2; move32(); + pDat_0[1] = accu1; move32(); + pDat_1[0] = accu4; move32(); + pDat_1[1] = L_negate(accu3); move32(); + + pDat_0 = pDat_0 + 2; + pDat_1 = pDat_1 - 2; + } + +#ifdef ENABLE_DCTIV_RESCALE +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + if (hrmode) +# endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + { + + scale = s_max(getScaleFactor32_lc3plus(pDat, L), 0); move16(); + + FOR (i = 0; i < L; i++) + { + pDat[i] = L_shl_pos(pDat[i], scale); move32(); + } + + *pDat_e = sub(*pDat_e, scale); move16(); + } +#endif + + BASOP_cfft_lc3plus(&pDat[0], &pDat[1], M_var, 2, pDat_e, workBuffer); + + pDat_0 = &pDat[0]; + pDat_1 = &pDat[L - 2]; + + idx = sin_step; + M2 = sub(shr_pos_pos(add(M_var, 1), 1), 1); + + /* Sin and Cos values are 0.0f and 1.0f */ +#ifdef ENABLE_HR_MODE + cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#else + cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#endif + + pDat_1[1] = L_negate(L_shr_pos(pDat_0[1], 1)); move32(); + pDat_0[0] = L_shr_pos(pDat_0[0], 1); move32(); + + FOR (i = 1; i < M2; i++) + { + pDat_0[1] = accu3; move32(); + pDat_1[0] = accu4; move32(); + + pDat_0 = pDat_0 + 2; + pDat_1 = pDat_1 - 2; + +#ifdef ENABLE_HR_MODE + cplxMpy32_32_32_2(accu1, accu2, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#else + cplxMpy32_32_16_2(accu1, accu2, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#endif + + idx += sin_step; + +#ifdef ENABLE_HR_MODE + cplxMpy32_32_32_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#else + cplxMpy32_32_16_2(accu3, accu4, pDat_1[0], pDat_1[1], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#endif + + pDat_1[1] = L_negate(accu1); move32(); + pDat_0[0] = accu2; move32(); + } + + pDat_0[1] = accu3; move32(); + pDat_1[0] = accu4; move32(); + + pDat_0 = pDat_0 + 2; + pDat_1 = pDat_1 - 2; + +#ifdef ENABLE_HR_MODE + cplxMpy32_32_32_2(accu3, accu4, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#else + cplxMpy32_32_16_2(accu3, accu4, pDat_0[1], pDat_0[0], sin_twiddle[idx].v.re, sin_twiddle[idx].v.im); +#endif + +/* Last Sin and Cos value pair are the same */ +#ifdef ENABLE_HR_MODE + accu1 = L_shr_pos(Mpy_32_32_lc3plus(pDat_1[0], TWIDDLE), 1); + accu2 = L_shr_pos(Mpy_32_32_lc3plus(pDat_1[1], TWIDDLE), 1); +#else + accu1 = L_shr_pos(Mpy_32_16_lc3plus(pDat_1[0], TWIDDLE), 1); + accu2 = L_shr_pos(Mpy_32_16_lc3plus(pDat_1[1], TWIDDLE), 1); +#endif + + pDat_1[0] = L_add(accu1, accu2); move32(); + pDat_0[1] = L_sub(accu1, accu2); move32(); + + pDat_1[1] = L_negate(accu3); move32(); + pDat_0[0] = accu4; move32(); + + /* twiddeling scale is 2 */ + *pDat_e = add(*pDat_e, 2); move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/dec_entropy.c b/lib_lc3plus/dec_entropy.c new file mode 100644 index 000000000..48512f9fe --- /dev/null +++ b/lib_lc3plus/dec_entropy.c @@ -0,0 +1,387 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits); + +static Word16 ac_dec_split_st2VQ_CW( /* local BER flag */ + const Word32 L_cwRx, /* max 25 bits */ + const Word32 L_szA, const Word32 L_szB, Word32 *L_cwA, Word32 *L_cwB, + Word16 *submodeLSB); + +void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, + Word16 L_spec, Word16 fs_idx, Word16 BW_cutoff_bits, Word16 *tns_numfilters, + Word16 *lsbMode, Word16 *lastnz, Word16 *bfi, Word16 *tns_order, Word16 *fac_ns_idx, + Word16 *gg_idx, Word16 *BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, + Word16 frame_dms) +{ + Dyn_Mem_Deluxe_In( + Word16 L, submodeLSB; + Word32 tmp32, tmp32lim; + Word16 gain_e, gain, submodeMSB, BER_detect; + Counter n; + UWord8 *ptr; + ); + + ptr = bytes; + *bp_side = shr_pos(sub(nbbits, 1), 3); + *mask_side = shl(1, sub(8, sub(nbbits, shl_pos(*bp_side, 3)))); + + /* Cutoff-detection */ + IF (BW_cutoff_bits > 0) + { + *BW_cutoff_idx = read_indice(ptr, bp_side, mask_side, BW_cutoff_bits); + /* check for bitflips */ + IF (sub(fs_idx, *BW_cutoff_idx) < 0) + { + *BW_cutoff_idx = fs_idx; + *bfi = 1; move16(); + Dyn_Mem_Deluxe_Out(); + return; + } + } + ELSE + { + *BW_cutoff_idx = fs_idx; + } + + /* Number of TNS filters */ + IF (sub(*BW_cutoff_idx, 3) >= 0 && frame_dms >= 50) + { + *tns_numfilters = 2; move16(); + } + ELSE + { + *tns_numfilters = 1; move16(); + } + + /* Decode number of ntuples */ + L = sub(14, norm_s(negate(L_spec))); + n = read_indice(ptr, bp_side, mask_side, L); + n = add(n, 1); + *lastnz = shl_pos(n, 1); + IF (sub(*lastnz, L_spec) > 0) + { + *bfi = 1; move16(); + Dyn_Mem_Deluxe_Out(); + return; + } + + /* Mode bit */ + *lsbMode = read_bit(ptr, bp_side, mask_side); + + /* Decode global-gain */ + *gg_idx = read_indice(ptr, bp_side, mask_side, 8); move16(); + tmp32 = L_shl_pos(L_mult0(*gg_idx, 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); /* get exponent */ + gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); + assert(gain >= 0); /* JSv, check if shr_pos(gain,1) is more appropriate) */ + gain = shr_r(gain, 1); + gain_e = add(gain_e, 1); + + /* Decode TNS on/off flag */ + tns_order[1] = 0; move16(); /* fix problem with uninitialized memory */ + FOR (n = 0; n < *tns_numfilters; n++) + { + tns_order[n] = read_bit(ptr, bp_side, mask_side); move16(); + } + + /* LTPF on/off */ +#ifdef ENABLE_HR_MODE + ltpf_idx[0] = read_bit(ptr, bp_side, mask_side); move16(); +#else + ltpf_idx[0] = read_indice(ptr, bp_side, mask_side, 1); move16(); +#endif + + /* Decode SNS VQ parameters - 1st stage (10 bits) */ +#ifdef ENABLE_HR_MODE + L = read_indice(ptr, bp_side, mask_side, 5 + 5); + L_scf_idx[0] = L_deposit_l(s_and(L, 0x1F)); /* stage1 LF 5 bits */ + L_scf_idx[1] = L_deposit_l(shr_pos(L, 5)); /* stage1 HF 5 bits */ +#else + L_scf_idx[0] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 5)); /* stage1 LF 5 bits */ + L_scf_idx[1] = L_deposit_l(read_indice(ptr, bp_side, mask_side, 5)); /* stage1 HF 5 bits */ +#endif + + /* Decode SNS VQ parameters - 2nd stage side-info (3-4 bits) */ + submodeMSB = read_bit(ptr, bp_side, mask_side); /* submodeMSB 1 bit */ + L_scf_idx[2] = L_deposit_l(shl_pos(submodeMSB, 1)); + ASSERT(sns_gainMSBbits[L_scf_idx[2]] > 0); + L_scf_idx[3] = L_deposit_l( + read_indice(ptr, bp_side, mask_side, sns_gainMSBbits[L_scf_idx[2]])); /* gains or gain MSBs 1-2 bits */ + L_scf_idx[4] = read_bit(ptr, bp_side, mask_side); /* shape LS 1 bit */ + + /* Decode SNS VQ parameters - 2nd stage data (24-25 bits) */ + IF (submodeMSB == 0) + { /* shape_j = 0, or 1 */ + /* regular mode A,B indexes integer multiplexed, total 24.x bits MPVQ codeword section A and codeword for + * section B */ + /* regular mode mode shape index total 24.9999 bits MPVQ codeword */ + tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 13)); + tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 13)); move16(); /*for ber state */ + BER_detect = + ac_dec_split_st2VQ_CW( /* local BER flag */ + tmp32, /* L_cwRx max 25 bits */ + sns_MPVQ_Sz[0][0], UL_addNsD(sns_MPVQ_Sz[0][1], sns_MPVQ_Sz[1][1]), /* 12+2 = 14 */ + (&L_scf_idx[5]), /* shape A */ + (&L_scf_idx[6]), /* shape B or gain LSB */ + &submodeLSB /* total submode update below */ + ); + IF (submodeLSB != 0) + { /* add gainLSB bit */ + L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_scf_idx[6]); + L_scf_idx[6] = -2L; + } + } + ELSE + { /* shape_j = 2 or 3 */ + ASSERT(submodeMSB == 1); + /* outlier mode shape index total 23.8536 + 19.5637 (19.5637 < (log2(2.^24 -2.^23.8537)) bits MPVQ + * codeword */ + tmp32 = L_deposit_l(read_indice(ptr, bp_side, mask_side, 12)); + tmp32 = L_or(tmp32, L_shl_pos(read_indice(ptr, bp_side, mask_side, 12), 12)); + L_scf_idx[5] = tmp32; move32(); /*shape outl_near or outl_far */ + submodeLSB = 0; move16(); + BER_detect = 0; move16(); + tmp32lim = L_add(sns_MPVQ_Sz[2][0], L_shl_pos(sns_MPVQ_Sz[3][0], 1)); + IF (L_sub(tmp32, tmp32lim) >= 0) + { + BER_detect = 1; move16(); + } + ELSE + { + tmp32 = L_sub(tmp32, sns_MPVQ_Sz[2][0]); /* a potential high index is computed */ + IF (tmp32 >= 0) + { + submodeLSB = 1; move16(); + ASSERT(tmp32 >= 0 && tmp32 < (Word32)(2 * sns_MPVQ_Sz[3][0])); + L_scf_idx[3] = L_add(L_shl_pos(L_scf_idx[3], 1), L_and(tmp32, 0x1)); /* add LSB_gain bit to gain MSBs */ + L_scf_idx[5] = L_shr_pos(tmp32, 1); /* MPVQ index with offset and gainLSB removed */ + L_scf_idx[6] = -2L; move32(); + } + ELSE + { + L_scf_idx[6] = -1L; move32(); + } + } + } + L_scf_idx[2] = + L_add(L_scf_idx[2], L_deposit_l(submodeLSB)); /* decoder internal signal shape_j = submode 0..3 to VQ */ + + IF (BER_detect > 0) + { + *bfi = 1; move16(); + Dyn_Mem_Deluxe_Out(); + return; + } + + /* LTPF data */ + IF (ltpf_idx[0] != 0) + { +#ifdef ENABLE_HR_MODE + L = read_indice(ptr, bp_side, mask_side, 1+9); move16(); + ltpf_idx[1] = s_and(L, 1); move16(); + ltpf_idx[2] = shr_pos(L, 1); move16(); +#else + ltpf_idx[1] = read_indice(ptr, bp_side, mask_side, 1); move16(); + ltpf_idx[2] = read_indice(ptr, bp_side, mask_side, 9); move16(); + +#endif + } + ELSE + { + ltpf_idx[1] = 0; move16(); + ltpf_idx[2] = 0; move16(); + } + + /* Decode noise-fac */ + *fac_ns_idx = read_indice(ptr, bp_side, mask_side, 3); move16(); + + Dyn_Mem_Deluxe_Out(); +} + +#ifdef ENABLE_PADDING +int paddingDec_fx(UWord8 *bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cutoff_bits, Word16 ep_enabled, + Word16 *total_padding, Word16 *np_zero) +{ + Word16 lastnz_threshold; + Word16 padding_len_bits, padding_len; + + Word16 bp_side; + Word16 nbbytes = shr(nbbits,3); + + Word16 mask_side; + UWord8 *ptr = bytes; + + Word16 lastnz; + Word16 nbits = sub(14, norm_s(negate(L_spec))); + if (sub(nbbits, nbits) < 0) + { + return 1; + } + *np_zero = 0; + + *total_padding = 0; + + bp_side = shr_pos(sub(nbbits, 1), 3); + mask_side = shl(1, sub(8, sub(nbbits, shl_pos(bp_side, 3)))); + + test(); + IF (sub(bp_side, 19) < 0 || sub(bp_side, LC3PLUS_MAX_BYTES ) >= 0) { + return 1; + } + + ptr = bytes; + + IF (BW_cutoff_bits > 0) + { + read_indice(ptr, &bp_side, &mask_side, BW_cutoff_bits); + move16(); + } + + lastnz = read_indice(ptr, &bp_side, &mask_side, nbits); + move16(); + + lastnz_threshold = sub(shl(1, nbits), 2); + + WHILE (lastnz == lastnz_threshold) + { + padding_len_bits = sub(sub(12, nbits), BW_cutoff_bits); + + /*Read padding length*/ + padding_len = read_indice(ptr, &bp_side, &mask_side, padding_len_bits); + move16(); + + /* Read 4 reserved bits */ + read_indice(ptr, &bp_side, &mask_side, 4); + move16(); + + IF (ep_enabled == 0) + { + /* Discard padding length bytes */ + bp_side = sub(bp_side, padding_len); + *total_padding = add(add(*total_padding, padding_len), 2); move16(); + } + ELSE + { + *total_padding = add(*total_padding, 2); move16(); + *np_zero = add(*np_zero, padding_len); move16(); + } + + /* test if we have less than 20 bytes left; if so frame is broken */ + IF (sub(sub(nbbytes,add(*total_padding,*np_zero)),20) < 0) { + return 1; + } + + /* Read bandwidth bits */ + IF (BW_cutoff_bits > 0) + { + read_indice(ptr, &bp_side, &mask_side, BW_cutoff_bits); + move16(); + } + + lastnz = read_indice(ptr, &bp_side, &mask_side, nbits); + move16(); + } + + IF (ep_enabled != 0) + { + *total_padding = add(*total_padding, *np_zero); move16(); + } + return 0; +} +#endif + +static __forceinline Word16 read_indice(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 numbits) +{ + Dyn_Mem_Deluxe_In( + Word16 indice, bit; + Counter i; + ); + + indice = read_bit(ptr, bp, mask); + + FOR (i = 1; i < numbits; i++) + { + bit = read_bit(ptr, bp, mask); + indice = add(indice, lshl_pos(bit, i)); + } + + Dyn_Mem_Deluxe_Out(); + return indice; +} + +static __forceinline Word16 ac_dec_split_st2VQ_CW( /* local BER flag */ + const Word32 L_cwRx, /* max 25 bits */ + const Word32 L_szA, const Word32 L_szB, Word32 *L_cwA, Word32 *L_cwB, + Word16 *submodeLSB) +{ + /* demultiplex: L_cwRx = L_cwB(21.z bits) * L_szA(3.y bits) + L_cwA(21.x bits)); */ + Word16 start, fin, ind; + Word32 L_tmp, L_max_size; + Counter i; + + L_max_size = (Word32)UL_Mpy_32_32((UWord32)L_szB, (UWord32)L_szA); /* may be tabled */ + + /* section B ind larger than 13 out of the possible 14 = 0..13 */ + IF (L_sub(L_cwRx, L_max_size) >= 0) + { + *L_cwA = L_deposit_l(0); + *L_cwB = L_deposit_l(0); + *submodeLSB = 0; move16(); + return (Word16)1; /* set berFlag and exit */ + } + + /*initial binary split of cw, select top or low half */ + start = 0; move16(); + + ASSERT((L_szB & 0x1L) == 0); /* this middle split only works if L_szB is even */ + if (L_sub(L_cwRx, L_shr_pos(L_max_size, 1)) >= 0) + { + start = L_shr_pos(L_szB, 1); /* top half start index */ + } + + /*linear loop over a low or a high section */ + ind = start; move16(); + L_tmp = L_negate(L_cwRx); /* search from negative side */ + + L_tmp = L_add(L_tmp, (Word32)UL_Mpy_32_32(UL_deposit_l((UWord16)start), (UWord32)L_szA)); + /* start is 0 or 7 */ /*non-fractional mult is (int)start * L_szA */ + + /* a short linear run over ceil(szB/2) = 7 values */ + + fin = add(start, shr_pos(L_szB, 1)); + FOR (i = start; i < fin; i++) + { + ind = add(ind, 1); + L_tmp = L_add(L_tmp, L_szA); + if (L_tmp > 0) + { + ind = sub(ind, 1); /* passed criteria point, keep index */ + } + } + + *L_cwB = L_deposit_l(ind); + *L_cwA = L_sub(L_cwRx, (Word32)UL_Mpy_32_32(UL_deposit_l((UWord16)ind), + (UWord32)L_szA)); /* non-fractional mult; (int)ind * L_szA */ + + ASSERT(*L_cwA >= 0 && *L_cwA < L_szA); + ASSERT(*L_cwB >= 0 && *L_cwB < L_szB); + + *submodeLSB = 0; + *L_cwB = L_sub(*L_cwB, 2); + if (*L_cwB < 0) + { + *submodeLSB = 1; move16(); + } + *L_cwB = L_mac0(*L_cwB, 2, *submodeLSB); /* add back gain ind if needed */ + + return 0; /* no BER */ +} diff --git a/lib_lc3plus/dec_lc3.c b/lib_lc3plus/dec_lc3.c new file mode 100644 index 000000000..40818106e --- /dev/null +++ b/lib_lc3plus/dec_lc3.c @@ -0,0 +1,788 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_sample, UWord8 *bs_in, void *s_out, Word16 bfi, + Word8 *scratchBuffer) +{ + Word16 scale; + Word32 offset; + Word16 fill_bits; + Word16 nf_seed, gg_idx, fac_ns_idx, q_fx_exp = 0; + Word16 bp_side, mask_side; + Word16 tns_numfilters, lsbMode, lastnz, BW_cutoff_idx, BW_cutoff_idx_nf; + Word16 zero_frame = 0; +#ifdef ENABLE_RFRAME + Word16 rframe = 0; +#endif + Word16 ltpf_idx[3]; + Word16 spec_inv_idx = 0; + Counter i; + + /* Buffers */ + Word16 *int_scf_fx_exp, tns_order[TNS_NUMFILTERS_MAX]; + UWord8 *resBitBuf; +#ifdef ENABLE_HR_MODE + Word32 *sqQdec; +#else + Word16 * sqQdec; + Word16 * int_scf_fx; +#endif + Word16 * x_fx, *indexes; + Word16 scf_q[M]; + Word32 * L_scf_idx; + Word32 * q_d_fx; + Word8 * currentScratch; + DecSetup *h_DecSetup = decoder->channel_setup[channel]; +#ifdef ENABLE_HR_MODE + Word32 *x_fx_ip; + Word32 *int_scf_fx_ip; + Word32 scf_q_ip[M]; +#endif + +#ifdef DYNMEM_COUNT + struct _dynmem + { + Counter i; + Word16 scale; + Word32 offset; + Word16 fill_bits; + Word16 nf_seed, gg_idx, fac_ns_idx, q_fx_exp; + Word16 bp_side, mask_side; + Word16 tns_numfilters, lsbMode, lastnz, BW_cutoff_idx, BW_cutoff_idx_nf; + Word16 zero_frame; + Word16 ltpf_idx[3]; +#ifdef ENABLE_RFRAME + Word16 rframe; +#endif + Word16 spec_inv_idx; + + /* Buffers */ + Word16 *int_scf_fx_exp, tns_order[TNS_NUMFILTERS_MAX]; + UWord8 *resBitBuf; +#ifdef ENABLE_HR_MODE + Word32 *sqQdec; +#else + Word16 *sqQdec; +#endif + Word16 *int_scf_fx, *x_fx, *indexes; + Word32 *L_scf_idx; + Word32 *q_d_fx; + Word8 * currentScratch; + Word16 scf_q[M]; +#ifdef ENABLE_HR_MODE + Word32 scf_q_ip[M]; +#endif + }; + Dyn_Mem_In("Dec_LC3_Channel", sizeof(struct _dynmem)); +#endif + +#ifdef DISABLE_PLC + UNUSED(decoder->plcMeth); +#endif + + + /* BUFFER INITIALISATION. Some buffers may overlap since they are not used in the whole decoding process */ + q_d_fx = scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN bytes */ +#ifdef ENABLE_HR_MODE + /* allocate memory for residual bits */ + if (decoder->hrmode) + { + resBitBuf = scratchAlign(q_d_fx, sizeof(*q_d_fx) * + decoder->frame_length); + basop_memset(resBitBuf, 0, sizeof(*resBitBuf) * MAX_RESBITS_LEN); + } + else +#endif + { + resBitBuf = scratchAlign(q_d_fx, sizeof(*q_d_fx) * + decoder->frame_length); /* Size = 2 * NPRM_RESQ = 2 * MAX_LEN bytes for + normal case and 2*MAX_RESBITS_LEN for hrmode */ + basop_memset(resBitBuf, 0, sizeof(*resBitBuf) * 2 * decoder->frame_length); + } + +#ifdef ENABLE_HR_MODE + indexes = scratchAlign(resBitBuf, sizeof(*resBitBuf) * MAX_RESBITS_LEN); +#else + indexes = scratchAlign(resBitBuf, sizeof(*resBitBuf) * 2 * decoder->frame_length); +#endif + memset(indexes, 0, sizeof(*indexes) * TNS_NUMFILTERS_MAX * MAXLAG); + + /* indexes Size = 2 * TNS_NUMFILTERS_MAX * MAXLAG = 32 bytes */ + + L_scf_idx = scratchAlign(indexes, sizeof(*indexes) * TNS_NUMFILTERS_MAX * + MAXLAG); /* Size = 4 * SCF_MAX_PARAM = 28 bytes -> aligned to 32 bytes */ + sqQdec = scratchAlign(L_scf_idx, sizeof(*L_scf_idx) * (SCF_MAX_PARAM)); /* Size = 2 * MAX_LEN bytes */ + int_scf_fx_exp = scratchAlign(sqQdec, sizeof(*sqQdec) * decoder->frame_length); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ +#ifndef ENABLE_HR_MODE + int_scf_fx = scratchAlign(int_scf_fx_exp, + sizeof(*int_scf_fx_exp) * MAX_BANDS_NUMBER); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ +#endif +#ifdef ENABLE_HR_MODE + x_fx = + scratchAlign(int_scf_fx_exp, sizeof(*int_scf_fx_exp) * MAX_BANDS_NUMBER); /* Size = 2 * (MAX_LEN + MDCT_MEM_LEN_MAX) = 2 + * MAX_LEN + 1.25 * MAX_LEN = 3.25 * MAX_LEN */ +#else + x_fx = + scratchAlign(q_d_fx, sizeof(*q_d_fx) * decoder->frame_length); /* Size = 2 * (MAX_LEN + MDCT_MEM_LEN_MAX) = 2 + * MAX_LEN + 1.25 * MAX_LEN = 3.25 * MAX_LEN */ +#endif + +#ifdef ENABLE_HR_MODE + x_fx_ip = scratchAlign(x_fx, sizeof(*x_fx) * (decoder->frame_length + decoder->stDec_ola_mem_fx_len)); + int_scf_fx_ip = scratchAlign(x_fx_ip, sizeof(*x_fx_ip) * (decoder->frame_length + decoder->stDec_ola_mem_fx_len)); + + currentScratch = scratchAlign(int_scf_fx_ip, sizeof(*int_scf_fx_ip) * 2 * MAX_BANDS_NUMBER); /* Size = 4 * MAX_LEN */ +#else + currentScratch = scratchAlign(x_fx, sizeof(*x_fx) * 4 * MAX_LEN); /* Size = 4 * MAX_LEN */ +#endif + +#ifdef DISABLE_PLC + memset(q_d_fx, 0, decoder->frame_length * sizeof(*q_d_fx)); +#endif + +#ifdef WMOPS + BASOP_sub_start("Decoder"); +#endif + +#ifdef ENABLE_RFRAME + IF (sub(bfi, 3) == 0) + { + bfi = 2; + move16(); + rframe = 1; + move16(); + } +#endif + + if (bfi != 1) + { +#ifdef WMOPS + BASOP_sub_sub_start("Dec(bfi=0)"); +#endif + } + else + { +#ifdef WMOPS + BASOP_sub_sub_start("Dec(bfi=1)"); +#endif + } + +#ifdef WMOPS + BASOP_sub_start("Entropy dec"); +#endif + IF (sub(bfi, 1) != 0) + { + processDecoderEntropy_fx(bs_in, &bp_side, &mask_side, h_DecSetup->total_bits, decoder->yLen, decoder->fs_idx, + decoder->BW_cutoff_bits, &tns_numfilters, &lsbMode, &lastnz, &bfi, tns_order, + &fac_ns_idx, &gg_idx, &BW_cutoff_idx, ltpf_idx, L_scf_idx, decoder->frame_dms); + BW_cutoff_idx_nf = BW_cutoff_idx; + move16(); + } +#ifdef WMOPS + BASOP_sub_end(); /* Entropy dec */ +#endif + +#ifdef WMOPS + BASOP_sub_start("Ari dec"); +#endif + IF (sub(bfi, 1) != 0) + { + processAriDecoder_fx(bs_in, &bp_side, &mask_side, h_DecSetup->total_bits, decoder->yLen, decoder->fs_idx, + h_DecSetup->enable_lpc_weighting, tns_numfilters, lsbMode, lastnz, &bfi, tns_order, + fac_ns_idx, gg_idx, decoder->frame_dms, + decoder->n_pc, decoder->be_bp_left, decoder->be_bp_right, 0, &spec_inv_idx, &scale, + &fill_bits, sqQdec, &nf_seed, resBitBuf, indexes, &zero_frame, currentScratch +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif + ); + +#ifdef ENABLE_RFRAME + test();test(); + IF (sub(rframe, 1) == 0 && zero_frame == 0 && sub(bfi, 1) != 0) + { + bfi = 2; + move16(); + Word16 max_bw_stopband = BW_cutoff_bin_all[BW_cutoff_idx]; + SWITCH (decoder->frame_dms) + { +#ifdef ENABLE_025_DMS_MODE + case 25: + max_bw_stopband = shr_pos(max_bw_stopband, 2); + BREAK; +#endif +#ifdef ENABLE_050_DMS_MODE + case 50: + max_bw_stopband = shr_pos(max_bw_stopband, 1); + BREAK; +#endif +#ifdef CR8_G_ADD_75MS + case 75: + max_bw_stopband = add(shr_pos(max_bw_stopband, 2), add(shr_pos(max_bw_stopband, 2), shr_pos(max_bw_stopband, 2))); + BREAK; +#endif + case 100: + BREAK; + } + + spec_inv_idx = s_max(lastnz, max_bw_stopband); + move16(); + } +#endif + + IF (bfi == 0) + { + processAriDecoderScaling_fx(sqQdec, decoder->yLen, q_d_fx, &q_fx_exp); + } + } +#ifdef WMOPS + BASOP_sub_end(); /* Ari dec */ +#endif + +#ifdef WMOPS + BASOP_sub_start("SnsQuantScfDec"); +#endif + IF (sub(bfi, 1) != 0) + { + /* currentScratch Size = 96 bytes */ +#ifdef ENABLE_HR_MODE + processSnsQuantizeScfDecoder_fx(L_scf_idx, scf_q_ip, currentScratch); + downshift_w32_arr(scf_q_ip, scf_q, 15, M); /* required for PLC */ +#else + processSnsQuantizeScfDecoder_fx(L_scf_idx, scf_q, currentScratch); +#endif + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("PLC::ComputeStabFac"); +#endif + if (h_DecSetup->plcAd) + { + processPLCcomputeStabFac_main(scf_q, h_DecSetup->plcAd->old_scf_q, h_DecSetup->plcAd->old_old_scf_q, bfi, + h_DecSetup->prev_bfi, h_DecSetup->prev_prev_bfi, &h_DecSetup->plcAd->stab_fac); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Partial Concealment"); +#endif + IF (sub(bfi, 1) != 0) + { + scale = 32767; + move16(); + + IF (h_DecSetup->plcAd) + { + scale = h_DecSetup->plcAd->stab_fac; + } + + processPCmain_fx(rframe, &bfi, decoder->yLen, decoder->frame_dms, h_DecSetup->q_old_res_fx, + &h_DecSetup->q_old_res_fx_exp, sqQdec, h_DecSetup->q_old_d_fx, spec_inv_idx, ltpf_idx[0], + scale, q_d_fx, &q_fx_exp, gg_idx, h_DecSetup->quantizedGainOff, &h_DecSetup->prev_gg, + &h_DecSetup->prev_gg_e, &BW_cutoff_idx_nf, &h_DecSetup->prev_BW_cutoff_idx_nf, fac_ns_idx, + &h_DecSetup->prev_fac_ns_fx, &h_DecSetup->pc_nbLostFramesInRow); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + + IF (sub(bfi, 1) != 0) + { +#ifdef WMOPS + BASOP_sub_start("Residual dec"); +#endif + processResidualDecoding_fx(q_d_fx, q_fx_exp, decoder->yLen, resBitBuf, fill_bits +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Noisefill"); +#endif + /* currentScratch Size = 2 * MAX_LEN bytes */ + IF (zero_frame == 0) + { + processNoiseFilling_fx(q_d_fx, nf_seed, q_fx_exp, fac_ns_idx, BW_cutoff_idx_nf, decoder->frame_dms, + h_DecSetup->prev_fac_ns_fx, spec_inv_idx, currentScratch +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif + ); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("applyGlobalGain"); +#endif + processApplyGlobalGain_fx(q_d_fx, &q_fx_exp, decoder->yLen, gg_idx, h_DecSetup->quantizedGainOff); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Tns_dec"); +#endif + /* currentScratch Size = 48 bytes */ + processTnsDecoder_fx(indexes, q_d_fx, decoder->yLen, tns_order, &q_fx_exp, BW_cutoff_idx, decoder->frame_dms, + currentScratch +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef ENABLE_HR_MODE +#ifdef WMOPS + BASOP_sub_start("SnsInterpScfDec"); +#endif + processSnsInterpolateScf_fx(scf_q_ip, int_scf_fx_ip, int_scf_fx_exp, 0, decoder->bands_number, currentScratch); + +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Mdct shaping_dec"); +#endif + processScfScaling(int_scf_fx_exp, decoder->bands_number, &q_fx_exp); + + processMdctShaping_fx(q_d_fx, int_scf_fx_ip, int_scf_fx_exp, decoder->bands_offset, decoder->bands_number); +#ifdef WMOPS + BASOP_sub_end(); +#endif +#else +#ifdef WMOPS + BASOP_sub_start("SnsInterpScfDec"); +#endif + /* currentScratch Size = 128 bytes */ + processSnsInterpolateScf_fx(scf_q, int_scf_fx, int_scf_fx_exp, 0, decoder->bands_number, currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Mdct shaping_dec"); +#endif + processScfScaling(int_scf_fx_exp, decoder->bands_number, &q_fx_exp); + processMdctShaping_fx(q_d_fx, int_scf_fx, int_scf_fx_exp, decoder->bands_offset, decoder->bands_number); +#ifdef WMOPS + BASOP_sub_end(); +#endif + /* end int_scf_fx */ +#endif /* ENABLE_HR_MODE */ + } + + /* x_fx_ip will be used to store h_DecSetup->stDec_ola_mem_fx returned by PLCmain_fx*/ + /* This will be upshifted to 32 bit overlap buffer outside of the PLCmain function */ +#ifdef ENABLE_HR_MODE + Word16 *plc_ola_mem = (Word16 *)x_fx_ip; + IF(sub(bfi, 1) == 0) + { + FOR(i = 0; i < decoder->stDec_ola_mem_fx_len; i++) + { + plc_ola_mem[i] = round_fx(h_DecSetup->stDec_ola_mem_fx[i]); + } + } +#endif + +#ifdef WMOPS + BASOP_sub_start("PLC::Main"); +#endif + /* currentScratch Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */ + processPLCmain_fx(decoder->plcMeth, &h_DecSetup->concealMethod, &h_DecSetup->nbLostFramesInRow, bfi, + h_DecSetup->prev_bfi, decoder->frame_length, decoder->la_zeroes, decoder->W_fx, x_fx, +#ifdef ENABLE_HR_MODE + plc_ola_mem, +#else + h_DecSetup->stDec_ola_mem_fx, +#endif + &h_DecSetup->stDec_ola_mem_fx_exp, h_DecSetup->q_old_d_fx, + &h_DecSetup->q_old_fx_exp, q_d_fx, &q_fx_exp, decoder->yLen, decoder->fs_idx, + decoder->bands_offset, decoder->bands_number, &h_DecSetup->plc_damping, h_DecSetup->ltpf_mem_pitch_int, + h_DecSetup->ltpf_mem_pitch_fr, &h_DecSetup->ns_cum_alpha, &h_DecSetup->ns_seed, h_DecSetup->plcAd, + decoder->frame_dms, currentScratch, &h_DecSetup->pc_nbLostFramesInRow +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + , h_DecSetup->rel_pitch_change +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + , decoder->alpha_type_2_table +#endif + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef ENABLE_HR_MODE + IF(sub(bfi, 1) == 0) + { + FOR(i = 0; i < decoder->stDec_ola_mem_fx_len; i++) + { + h_DecSetup->stDec_ola_mem_fx[i] = L_deposit_h(plc_ola_mem[i]); + } + } +#endif + +#ifdef WMOPS + BASOP_sub_start("PLC/PC::DampingScrambling"); +#endif + if (h_DecSetup->plcAd) + { + processPLCDampingScrambling_main_fx( + bfi, h_DecSetup->concealMethod, h_DecSetup->nbLostFramesInRow, &h_DecSetup->plcAd->cum_fflcAtten, + h_DecSetup->pc_nbLostFramesInRow, &h_DecSetup->ns_seed, &h_DecSetup->pc_seed, + h_DecSetup->ltpf_mem_pitch_int, ltpf_idx[0], q_d_fx, &q_fx_exp, h_DecSetup->q_old_d_fx, + &h_DecSetup->q_old_fx_exp, decoder->yLen, h_DecSetup->plcAd->stab_fac, decoder->frame_dms, + &h_DecSetup->plcAd->cum_fading_slow, &h_DecSetup->plcAd->cum_fading_fast, spec_inv_idx +#ifdef CR8_A_PLC_FADEOUT_TUNING + , h_DecSetup->plcAd->plc_fadeout_type +#endif + ); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Imdct"); +#endif + /* currentScratch Size = 4 * MAX_LEN */ + ProcessingIMDCT(q_d_fx, &q_fx_exp, decoder->W_fx, h_DecSetup->stDec_ola_mem_fx, &h_DecSetup->stDec_ola_mem_fx_exp, +#ifdef ENABLE_HR_MODE + x_fx_ip, +#else + x_fx, +#endif + decoder->W_size, decoder->frame_length, decoder->stDec_ola_mem_fx_len, decoder->frame_dms, + h_DecSetup->concealMethod, bfi, h_DecSetup->prev_bfi, h_DecSetup->nbLostFramesInRow, + h_DecSetup->plcAd, + currentScratch +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif + ); + +#ifdef ENABLE_HR_MODE + IF(sub(bfi, 1) != 0 || sub(h_DecSetup->concealMethod, LC3_CON_TEC_NS_STD) == 0 || sub(h_DecSetup->concealMethod, LC3_CON_TEC_NS_ADV) == 0 || sub(h_DecSetup->concealMethod, LC3_CON_TEC_FREQ_MUTING) == 0) + { + round_w32tow16_arr(x_fx_ip, x_fx, decoder->frame_length); + } + ELSE + { + FOR(i = 0; i < decoder->frame_length; i++) + { + x_fx_ip[i] = L_deposit_h(x_fx[i]); + } + } +#endif /* ENABLE_HR_MODE */ + +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("PLC::Update"); +#endif + + processPLCupdate_fx(h_DecSetup->plcAd, x_fx, q_fx_exp, h_DecSetup->concealMethod, decoder->frame_length, + decoder->fs_idx, &h_DecSetup->nbLostFramesInRow, &h_DecSetup->prev_prev_bfi, + &h_DecSetup->prev_bfi, bfi, scf_q, &h_DecSetup->ns_cum_alpha +#ifdef ENABLE_HR_MODE + , decoder->hrmode +#endif + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("LtpfDec"); +#endif + /* currentScratch Size = 0.5 * MAX_LEN + 20 bytes */ + process_ltpf_decoder_fx(&q_fx_exp, decoder->frame_length, decoder->ltpf_mem_x_len, decoder->fs_idx, + decoder->ltpf_mem_y_len, &h_DecSetup->ltpf_mem_e, x_fx, h_DecSetup->ltpf_mem_x, x_fx, + h_DecSetup->ltpf_mem_y, ltpf_idx[0], ltpf_idx[1], ltpf_idx[2], + &h_DecSetup->ltpf_mem_pitch_int, &h_DecSetup->ltpf_mem_pitch_fr, &h_DecSetup->ltpf_mem_gain, + &h_DecSetup->ltpf_mem_active, h_DecSetup->ltpf_scale_fac_idx, bfi, + h_DecSetup->concealMethod, + h_DecSetup->plc_damping, &h_DecSetup->ltpf_mem_scale_fac_idx, +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + &h_DecSetup->rel_pitch_change, decoder->hrmode, decoder->frame_dms, +#endif + currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef ENABLE_HR_MODE + IF (!(decoder->hrmode)) + { + FOR (i = 0; i < decoder->frame_length; i++) + { + x_fx_ip[i] = L_deposit_h(x_fx[i]); + } + } +#endif + +#ifdef WMOPS + BASOP_sub_start("Output scaling"); +#endif + { + scale = sub(sub(31 + 16, bits_per_sample), q_fx_exp); + offset = L_shr_sat(32768, sub(16, scale)); + IF (bits_per_sample == 16) + { + scale = sub(15, q_fx_exp); + FOR (i = 0; i < decoder->frame_length; i++) + { +#ifdef ENABLE_HR_MODE + ((Word16 *)s_out)[i] = round_fx_sat(L_shr_sat(x_fx_ip[i], scale)); +#else + ((Word16 *)s_out)[i] = round_fx_sat(L_shr_sat(L_deposit_h(x_fx[i]), scale)); +#endif + move16(); + } + } + ELSE + { + FOR (i = 0; i < decoder->frame_length; i++) + { +#ifdef ENABLE_HR_MODE + ((Word32 *)s_out)[i] = L_shr_sat(L_add_sat(x_fx_ip[i], offset), scale); +#else + ((Word32 *)s_out)[i] = L_shr_sat(L_add_sat(L_deposit_h(x_fx[i]), offset), scale); +#endif + move32(); + } + } + } +#ifdef WMOPS + BASOP_sub_end(); /* Output scaling */ +#endif + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_end(); /* Decoder */ +#endif + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + return bfi; +} + +/* num_bytes = 0 -> bad frame */ +LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, void **output, int bits_per_sample, void *scratch, + int bfi_ext) +{ + int ch = 0, bfi = bfi_ext; + LC3PLUS_Error err = LC3PLUS_OK; + int fec_num_bytes; + int lc3_num_bytes; + int lc3_channel_num_bytes; + int channel_bfi, out_bfi; + Word16 channel_epmr; + + if (bfi == 0) + { + bfi = !num_bytes; + } + + if (decoder->ep_enabled) + { + decoder->combined_channel_coding = decoder->channels > 1 && num_bytes <= 160; + + if (decoder->combined_channel_coding) + { + fec_num_bytes = num_bytes; + +#ifdef WMOPS + BASOP_sub_start("fec_dec"); +#endif + + decoder->error_report = + fec_decoder(input, fec_num_bytes, &lc3_num_bytes, &decoder->epmr, decoder->combined_channel_coding, + &decoder->n_pccw, &bfi, &decoder->be_bp_left, &decoder->be_bp_right, &decoder->n_pc, + &decoder->m_fec, scratch); + +#ifdef WMOPS + BASOP_sub_end(); +#endif + + for (ch = 0; ch < decoder->channels; ch++) + { + lc3_channel_num_bytes = lc3_num_bytes / decoder->channels + (ch < (lc3_num_bytes % decoder->channels)); + + + if (bfi != 1 && lc3_channel_num_bytes != decoder->channel_setup[ch]->last_size) + { + err = update_dec_bitrate(decoder, ch, lc3_channel_num_bytes); + + if (err) + { + bfi = 1; + } + else + { + decoder->channel_setup[ch]->last_size = lc3_channel_num_bytes; + } + } + + bfi = Dec_LC3PLUS_Channel(decoder, ch, bits_per_sample, input, output[ch], bfi, scratch); + input += decoder->channel_setup[ch]->targetBytes; + } + } + else + { + decoder->epmr = 12; + out_bfi = 0; + + for (ch = 0; ch < decoder->channels; ch++) + { + fec_num_bytes = num_bytes / decoder->channels + (ch < (num_bytes % decoder->channels)); + +#ifdef WMOPS + BASOP_sub_start("fec_dec"); +#endif + + channel_bfi = bfi; + + decoder->error_report = + fec_decoder(input, fec_num_bytes, &lc3_num_bytes, &channel_epmr, decoder->combined_channel_coding, + &decoder->n_pccw, &channel_bfi, &decoder->be_bp_left, &decoder->be_bp_right, + &decoder->n_pc, &decoder->m_fec, scratch); + +#ifdef WMOPS + BASOP_sub_end(); +#endif + + decoder->epmr = MIN(decoder->epmr, channel_epmr); + + +#ifdef ENABLE_PADDING + if (channel_bfi != 1) + { + Word16 padding_len, np_zero; + + if (paddingDec_fx(input, shl(lc3_num_bytes, 3), decoder->yLen, decoder->BW_cutoff_bits, + decoder->ep_enabled, &padding_len, &np_zero)) + { + channel_bfi = 1; + } + + input = input + np_zero; + decoder->n_pc = s_max(decoder->n_pc - (2 * np_zero), 0); + + if (channel_bfi == 2) + { + if (decoder->be_bp_right < (8 * np_zero)) + { + channel_bfi = 0; + decoder->be_bp_left = -1; + decoder->be_bp_right = -1; + } + else + { + decoder->be_bp_right = decoder->be_bp_right - (8 * np_zero); + decoder->be_bp_left = s_max(decoder->be_bp_left - (8 * np_zero), 0); + } + } + + lc3_num_bytes = lc3_num_bytes - padding_len; + } +#endif + + if (channel_bfi != 1 && lc3_num_bytes != decoder->channel_setup[ch]->last_size) + { + err = update_dec_bitrate(decoder, ch, lc3_num_bytes); + if (err) + { + channel_bfi = 1; + } + else + { + decoder->channel_setup[ch]->last_size = lc3_num_bytes; + } + } + + channel_bfi = Dec_LC3PLUS_Channel(decoder, ch, bits_per_sample, input, output[ch], channel_bfi, scratch); + + out_bfi |= channel_bfi; + input += fec_num_bytes; + } + + bfi = out_bfi & 1; + } + } + else + { + for (ch = 0; ch < decoder->channels; ch++) + { + lc3_num_bytes = num_bytes / decoder->channels + (ch < (num_bytes % decoder->channels)); + +#ifdef ENABLE_PADDING + if (bfi != 1) + { + Word16 padding_len, np_zero; + + if (paddingDec_fx(input, shl(lc3_num_bytes, 3), decoder->yLen, decoder->BW_cutoff_bits, + decoder->ep_enabled, &padding_len, &np_zero)) + { + bfi = 1; + } + + lc3_num_bytes = lc3_num_bytes - padding_len; + if (lc3_num_bytes < 20 || lc3_num_bytes > LC3PLUS_MAX_BYTES) + { + bfi = 1; /* mark frame as broken if frame sizeif below the minimum of 20 bytes */ + } + } +#endif + + if (bfi != 1 && lc3_num_bytes != decoder->channel_setup[ch]->last_size) + { + err = update_dec_bitrate(decoder, ch, lc3_num_bytes); + if (err) + { + bfi = 1; + } + else + { + decoder->channel_setup[ch]->last_size = lc3_num_bytes; + } + } + + bfi = Dec_LC3PLUS_Channel(decoder, ch, bits_per_sample, input, output[ch], bfi, scratch); + input += decoder->channel_setup[ch]->targetBytes; + } + } + + return bfi == 1 ? LC3PLUS_DECODE_ERROR : LC3PLUS_OK; +} diff --git a/lib_lc3plus/defines.h b/lib_lc3plus/defines.h new file mode 100644 index 000000000..c9909ddf2 --- /dev/null +++ b/lib_lc3plus/defines.h @@ -0,0 +1,734 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef DEFINES_H +#define DEFINES_H + +#ifndef DISABLE_HR_MODE +# define ENABLE_HR_MODE +#endif + +#ifdef ENABLE_HR_MODE +# define MAX_BW_HR 960 +#endif + +#ifdef ENABLE_HR_MODE +# define extractW16(a) extract_h(a) +#else +# define extractW16(a) (a) +#endif + +#define MAX_BR 320000 /* 400 * 800 */ + +/* FUNCTION MACROS */ +/* NB, divisions in some of these MACROs, use mainly for initial setup, do not use in loops */ +#define CEILING(x, y) (((x) + (y)-1) / (y)) + +#define FRAME2FS_IDX(x) (x / 100) /* 80 -> 0, 160 -> 1, 240 -> 2, 320 -> 3, 480 -> 4 */ +#ifdef ENABLE_HR_MODE +# define FS2FS_IDX(x) ((x) == 96000 ? 5 : (x) / 10000) /* 8000 -> 0, 16000 -> 1, 24000 -> 2, 32000 -> 3, 48000 -> 4, 96000 -> 5 */ +#else +# define FS2FS_IDX(x) (x / 10000) /* 8000 -> 0, 16000 -> 1, 24000 -> 2, 32000 -> 3, 48000 -> 4 */ +#endif + +#define UNUSED(x) (void)(x) /* silence unused parameter warning */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define STATIC_ASSERTS(cond, s) typedef char assert_##s[(cond) ? 1 : -1] +#define STATIC_ASSERTI(cond, i) STATIC_ASSERTS(cond, i) +#define STATIC_ASSERT(cond) STATIC_ASSERTI(cond, __LINE__) +#define TRACE(x) PRINTF("%s:%i %s = %i\n", __FILE__, __LINE__, #x, (int)(x)) + +/* For dynamic memory calculations */ +#define CODEC_FS(fs) ((fs) == 44100 ? 48000 : (fs)) + +#define DYN_MAX_LEN(fs) (CODEC_FS(fs) / 100) +#define DYN_MAX_LEN_EXT(fs) MAX(CODEC_FS(fs) / 100, 160) /* extension to length 160 for NB(fs=8000) */ +#define DYN_MAX_LPROT(fs) ((512 * (CODEC_FS(fs) / 100)) / 320) + +#define DYN_MAX_PLOCS(fs) (DYN_MAX_LPROT(fs) / 4 + 1) +#define DYN_MAX_MDCT_LEN(fs) (DYN_MAX_LEN(fs) - (180 * DYN_MAX_LEN(fs) / 480)) + +#define MAX_PITCH_FS(fs) (CEILING((MAX_PITCH_12K8 * CODEC_FS(fs)), (12800))) + +/* get the maximum buffer size assuming 10 ms framing */ +/* MAX_PITCH was previously always the highest fs in the current SUBSET , i.e. typically 48 kHz */ +/* now fs(from incoming wav file) adaptive MAX_PITCH_FS(fs) is used instead */ +#define DYN_MAX_LEN_PCM_PLC_CLASSIFIER(fs) \ + (MAX_PITCH_FS(fs) + DYN_MAX_LEN(fs)) /* CLASSIFIER PCM memory requirement */ +#define DYN_MAX_LEN_PCM_PLC_TDCAPPLYFILTER(fs) \ + ((M + 1) + MAX_PITCH_FS(fs) + (DYN_MAX_LEN(fs) / 2)) /* TDC filtering PCM memory requirement */ + +#ifdef ENABLE_HR_MODE +# define DYN_MAX_LEN_PCM_PLC(fs) (MAX_PITCH_FS(fs) + DYN_MAX_LEN(fs)) +#else +# define DYN_MAX_LEN_PCM_PLC(fs) MAX(DYN_MAX_LEN_PCM_PLC_CLASSIFIER(fs), DYN_MAX_LEN_PCM_PLC_TDCAPPLYFILTER(fs)) +#endif + +#define FRAME_MS_BLOCK 25 + +/* OPTIONS */ +#define ENABLE_2_5MS_MODE +#define ENABLE_5MS_MODE +#define ENABLE_075_DMS_MODE +#define ENABLE_10_MS_MODE +#define ENABLE_ADVANCED_PLC +#define ENABLE_ADVANCED_PLC_DEFAULT +#define ENABLE_BW_CONTROLLER +#define ENABLE_ERROR_PROTECTION +#define ENABLE_RFRAME +#define ENABLE_PC +#define ENABLE_PLC +#define ENABLE_PADDING +/* flags */ +#define ENABLE_BANDWIDTH_FLAG +#define ENABLE_RBANDWIDTH_FLAG +#define ENABLE_EP_MODE_FLAG +#define ENABLE_FRAME_MS_FLAG + +#define CR8_A_PLC_FADEOUT_TUNING /* Adapt PLC fadeout to avoid gaps in signal */ +#define CR8_E_TONE_DETECTOR /* Tone detector for hrmode to deactivate TNS - improves SNR and THD+N */ +#define CR8_F_ADAPT_MDCT_DCT_PRECISION +#define CR8_G_ADD_75MS + + +#define CR9_B_FIX_MDCT_OVERFLOW /* Fix overflow */ +#define CR9_C_FIX_DCT2_OVERFLOW /* Fix overflow */ + +#define CR9_F_PITCH_WIN_LEN_FIX /* Increase window length for pitch calculation */ +#define CR9_G_IMPROVE_TDC /* summarize G,H,J,L,N */ +#ifdef CR9_G_IMPROVE_TDC +# define CR9_G_PLC_NS_TDC_FIX /* Always use TDC if pitch > 0 */ +# define CR9_H_REMOVE_SWITCH_TO_PLC_NS +# define CR9_J_SLOW_TDC_FADEOUT +# define CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER +# ifdef ENABLE_HR_MODE +# define CR10_A_ATTENUATION_CURVE_SELECTOR +# ifdef CR10_A_ATTENUATION_CURVE_SELECTOR +# define CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH +# endif +# endif +#endif /* CR9_G_IMPROVE_TDC */ +#define CR9_I_INC_TDC_FADEOUT_LEN +#define CR9_K_REDUCE_NORM_CORR_TH +#define CR9_M_FIX_DIV_ZERO + +#ifndef NO_POST_REL_CHANGES +/* Post-release non-bitexact changes */ + +#define CR11_A_FIX_IN_PLC_LONGTERM_STATISTIC + +#endif /* NO_POST_REL_CHANGES Post-release changes */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING +# ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER +# ifdef CR9_K_REDUCE_NORM_CORR_TH +# define THRESH_100_DMS_TDC_CNT 9 +# define THRESH_100_DMS_NS_CNT 7 +# define THRESH_100_DMS_TDC_NS_CNT 73 +# define THRESH_075_DMS_TDC_CNT 7 +# define THRESH_075_DMS_NS_CNT 7 +# define THRESH_075_DMS_TDC_NS_CNT 87 +# define THRESH_050_DMS_TDC_CNT 22 +# define THRESH_050_DMS_NS_CNT 15 +# define THRESH_050_DMS_TDC_NS_CNT 141 +# define THRESH_025_DMS_TDC_CNT 20 +# define THRESH_025_DMS_NS_CNT 21 +# define THRESH_025_DMS_TDC_NS_CNT 278 +# else +# define THRESH_100_DMS_TDC_CNT 3 +# define THRESH_100_DMS_NS_CNT 35 +# define THRESH_100_DMS_TDC_NS_CNT 114 +# define THRESH_075_DMS_TDC_CNT 6 +# define THRESH_075_DMS_NS_CNT 37 +# define THRESH_075_DMS_TDC_NS_CNT 130 +# define THRESH_050_DMS_TDC_CNT 12 +# define THRESH_050_DMS_NS_CNT 55 +# define THRESH_050_DMS_TDC_NS_CNT 227 +# define THRESH_025_DMS_TDC_CNT 10 +# define THRESH_025_DMS_NS_CNT 138 +# define THRESH_025_DMS_TDC_NS_CNT 431 +# endif +# else +# define FAC1_FADEOUT 6710886 /* 0.2 * 2^25 */ +# define SHIFT1_FADEOUT 25-15 /* 25 - 16 */ +# define FAC2_FADEOUT 50331648 /* 1.5 * 2^25 */ +# define SHIFT2_FADEOUT 25-15 /* 25 - 16 */ +# define FAC3_FADEOUT 58720256 /* 1.75 * 2^25 */ +# define SHIFT3_FADEOUT 25-15 /* 25 - 16 */ +# endif +# define PLC_LONGTERM_ANALYSIS_MS 200 /* Nominal analysis window 2000 ms */ +# define PLC_LONGTERM_ANALYSIS_STARTUP_FILL (Word16)(0.5*32768.0) /* 16384/32768 == 0.5 required buffer fill amount, set to 0.0 to not require any fill at all */ +#endif /* CR8_A_PLC_FADEOUT_TUNING */ + +#define REL_PITCH_THRESH 11796 + +# define MIN_BR_100DMS 16000 /* 20 * 800 * 100/100 */ +# ifdef SUBSET_NB +# define MAX_BR_100DMS_NB 114400 /* for 100ms at 8kHz */ +# endif +# ifdef SUBSET_WB +# define MAX_BR_100DMS_WB 221600 /* for 100ms at 16kHz */ +# endif +# ifdef SUBSET_SSWB +# define MAX_BR_100DMS_SSWB 314400 /* for 100ms at 24kHz */ +# endif + +/* G192 bitstream writing/reading */ +#define G192_GOOD_FRAME 0x6B21 +#define G192_BAD_FRAME 0x6B20 +#define G192_REDUNDANCY_FRAME 0x6B22 +#define G192_ZERO 0x007F +#define G192_ONE 0x0081 +#define READ_G192FER /* allow C executable to also read G192 formatted FER files */ + +#ifdef DEBUG +#ifdef READ_G192FER +# define READ_G192_FER_BYTE /* Allow C executable to also read G192 byte formatted FER files 0x20=BAD , 0x21=Good */ +#endif +#endif + + +// #define DYNMEM_COUNT +#define STAMEM_COUNT + + +/* +do not change __forceinline for mex compilation using gcc6.3.0 or larger + gcc630 supported by MATLAB 2018b, via Mingw "app" + */ +#ifdef __GNUC__ +# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +# define GCC_VERSION 0 +#endif + +/* Define __forceinline as empty if ARM not activated to avoid any errors */ +#undef __forceinline +/* The above undef is needed to compile using make_mex.m without the following warning in Matlab for windows */ +#define __forceinline + +/* SUBSETS */ +#if !(defined(SUBSET_NB) || defined(SUBSET_WB) || defined(SUBSET_SSWB) || defined(SUBSET_SWB) || defined(SUBSET_FB) || defined(SUBSET_UB)) +# define SUBSET_NB +# define SUBSET_WB +# define SUBSET_SSWB +# define SUBSET_SWB +# define SUBSET_FB +# ifdef ENABLE_HR_MODE +# define SUBSET_UB +# endif +#endif + +# define MIN_BR_100DMS 16000 /* 20 * 800 * 100/100 */ +# define MIN_BR_025DMS 64000 /* 20 * 800 * 100/ 25 */ +# define MIN_BR_050DMS 32000 /* 20 * 800 * 100/ 50 */ +# define MAX_BR_050DMS_NB 260800 /* 163 * 800 * 100/ 50 */ +# ifdef SUBSET_NB +# define MAX_BR_100DMS_NB 114400 /* for 100ms at 8kHz */ +# endif +# ifdef SUBSET_WB +# define MAX_BR_100DMS_WB 221600 /* for 100ms at 16kHz */ +# endif +# ifdef SUBSET_SSWB +# define MAX_BR_100DMS_SSWB 314400 /* for 100ms at 24kHz */ +# endif + +#ifdef CR8_G_ADD_75MS +# define MIN_BR_075DMS_48KHZ_HR ((int)124800/ 800/2)* 800 +# define MIN_BR_075DMS_96KHZ_HR ((int)149600/ 800/2)* 800 +# define MIN_BR_075DMS 21334 /* ceil( 20 * 800 * 100/ 75) */ +# define MAX_BR_075DMS 426667 /* ceil(400 * 800 * 100/ 75) */ +# define MAX_BR_075DMS_NB 152534 /* ceil(143 * 800 * 100/ 75) */ +# define MAX_BR_075DMS_WB 295467 /* ceil(277 * 800 * 100/ 75) */ +# define MAX_BR_075DMS_SSWB 419200 /* ceil(393 * 800 * 100/ 75) */ + +# define NOISEFILLWIDTH_7_5MS 2 +# define NOISEFILLSTART_7_5MS 18 +#endif + +#define PACK_RESBITS + +/* FRAME/BUFFER */ +#ifdef SUBSET_UB +# define MAX_LEN 960 /* = 10ms at 96kHz */ +#elif defined SUBSET_FB +# define MAX_LEN 480 /* = 10ms at 48kHz */ +#elif defined(SUBSET_SWB) +# define MAX_LEN 320 /* = 10ms at 32kHz */ +#elif defined(SUBSET_SSWB) +# define MAX_LEN 240 /* = 10ms at 24kHz */ +#elif defined(SUBSET_WB) +# define MAX_LEN 160 /* = 10ms at 16kHz */ +#elif defined(SUBSET_NB) +# define MAX_LEN 80 /* = 10ms at 8kHz */ +#endif + +#ifdef ENABLE_HR_MODE +# define ENABLE_FFT_RESCALE +# define ENABLE_FFT_30X16 +# define ENABLE_DCTIV_RESCALE + +# define EXT_RES_ITER_MAX 20 +# define MAX_RESBITS 5000 +# define HR_MODE_SCRATCH_SIZE 60 +#else /* ENABLE_HR_MODE */ +# define MAX_RESBITS MAX_LEN +#endif /* ENABLE_HR_MODE */ + +/* BW Cutoff-Detection */ +#define MAX_BW_BANDS_NUMBER 5 + +#ifdef ENABLE_HR_MODE +# define RESBITS_PACK_SHIFT 3 +# define RESBITS_PACK_N (1<<(RESBITS_PACK_SHIFT)) +# define RESBITS_PACK_MASK (RESBITS_PACK_N - 1) +# define MAX_RESBITS_LEN ((MAX_RESBITS + RESBITS_PACK_MASK) >> RESBITS_PACK_SHIFT) +# define MAX_RESBITS_LEN_32BIT_ALIGN (((MAX_RESBITS_LEN + 3)/4)*4) +#else /* ENABLE_HR_MODE */ +# define MAX_RESBITS_LEN (MAX_RESBITS) +# define MAX_RESBITS_LEN_32BIT_ALIGN (((MAX_RESBITS_LEN + 3)/4)*4) +#endif /* ENABLE_HR_MODE */ + +#define MAX_CHANNELS 2 +#define MIN_NBYTES 20 /* 100dms: 16 kbps at !=44.1kHz, 14.7kbps at 44.1kHz + 50dms: 32 kbps at !=44.1kHz, 29.4kbps at 44.1kHz + 25dms: 64 kbps at !=44.1kHz, 58.8kbps at 44.1kHz */ +#define MAX_NBYTES_025 100 /* any dms: 320 kbps at !=44.1kHz, 294 kbps at 44.1kHz */ +#define MAX_NBYTES_050 200 /* any dms: 320 kbps at !=44.1kHz, 294 kbps at 44.1kHz */ +#define MAX_NBYTES_075 400 /* any dms: 320 kbps at !=44.1kHz, 294 kbps at 44.1kHz */ +#define MAX_NBYTES_100 400 /* any dms: 320 kbps at !=44.1kHz, 294 kbps at 44.1kHz */ +#ifdef ENABLE_HR_MODE +# define MIN_BR_25MS_48KHZ_HR ((int)172800/3200/2)*3200 +# define MIN_BR_25MS_96KHZ_HR ((int)198400/3200/2)*3200 +# define MIN_BR_50MS_48KHZ_HR ((int)148800/1600/2)*1600 +# define MIN_BR_50MS_96KHZ_HR ((int)174400/1600/2)*1600 +# define MIN_BR_100MS_48KHZ_HR ((int)124800/800/2)*800 +# define MIN_BR_100MS_96KHZ_HR ((int)149600/800/2)*800 +# define MAX_NBYTES_RED_HR 625 /* From table 5.2 */ +# define BYTESBUFSIZE (MAX_NBYTES_RED_HR * LC3PLUS_MAX_CHANNELS) +#else +# define BYTESBUFSIZE (MAX_NBYTES_100 * LC3PLUS_MAX_CHANNELS) +#endif +#define MAX_BW_BIN 400 +#define FEC_SLOT_BYTES_MIN 40 +# define FEC_SLOT_BYTES_MAX 400 +#if MAX_BW_BIN > MAX_LEN +# define MAX_BW MAX_LEN +#else +# define MAX_BW MAX_BW_BIN +#endif + +#define NUM_OFFSETS 7 +#define NUM_SAMP_FREQ 6 + +/* SCF */ +#define M 16 /* LPC_ORDER */ +#define MAX_BANDS_NUMBER 64 +#define MAX_BANDS_NUMBER_PLC 80 +#define PVQ_MAX_VEC_SIZE M +#define KMAX_FX 10 /* N=10 */ +#define K_OUTL_FAR 6 +#define MPVQ_SZ_OUTL_FAR (1549824U >> 1) +#define TOTBITS_SHAPE OUTL_FAR(1.0 + 19.5637) +#define SQRT_EN_MAX_FX 64 /* table size, for fast inv_sqrt */ +#define N_SETA 10 +#define N_SETB (PVQ_MAX_VEC_SIZE - N_SETA) + +#define SNS_DAMPING 27853 /* 0.85 in Q15 */ +#ifdef ENABLE_HR_MODE +# define SNS_DAMPING_HRMODE 19661 /* 0.6 in Q15 */ +# define SNS_DAMPING_HRMODE_UB_10MS 6881 /* 0.21 in Q15 */ +# define SNS_DAMPING_HRMODE_UB_7_5MS 5898 /* 0.18 in Q15 */ +# define SNS_DAMPING_HRMODE_UB_5MS 4915 /* 0.15 in Q15 */ +# define SNS_DAMPING_HRMODE_UB_2_5MS 4915 /* 0.15 in Q15 */ +#endif + +/* PVQ VQ setup */ +#define VQMODES26 \ + ((0 << 4) + (1 << 3) + (1 << 2) + (1 << 1) + \ + (1 << 0)) /* select all shapes, including extended lf, and new far \ + shape for MODE26, add extreme far mode not enabled */ +#define SCF_STAGE1_MAX_BITS (5 + 5) /* typically only (5+5) used */ +#define SCF_STAGE1_NBCDKENTRIES 32 +#define SCF_STAGE2_MAX_GAIN_BITS 2 +#define SCF_STAGE2_NB_MODE_BITS 1 +#define SCF_STAGE2_MAX_NB_SHAPES 3 +#define SCF_MAX_PARAM 7 /* (L+H) + submode_MSB +gain+(Ia_leads+Ia_mpvq)+(Ib_joint_mpvq), submode-LSB */ +#define SCF_MAX_PARAM_ST2 (SCF_MAX_PARAM - 2) +#define N_SCF_SHAPES_ST2 4 +#define N_SCF_SHAPE_SETUPS 1 + +/* ARITHMETIC ENCODER */ +#define NBITS_CONTEXT 8 +#define NBITS_RATEQ 2 +#define A_THRES_SHIFT 2 +#define A_THRES (1 << A_THRES_SHIFT) +#define VAL_ESC 16 +#define SYM_BITS_Q 11 + +/* RESIDUAL CODING */ +#define NPRM_RESQ MAX_LEN + +/* NOISE FILLING */ +#define NOISEFILLWIDTH 3 +#define NOISEFILLSTART 24 +#define NOISEFILLWIDTH_5MS 1 +#define NOISEFILLSTART_5MS 12 +#define NOISEFILLWIDTH_2_5MS 1 +#define NOISEFILLSTART_2_5MS 6 + +/* MDCT */ +#ifdef ENABLE_HR_MODE +# define TWIDDLE ((Word32)0x5a82799a) +#else +# define TWIDDLE WORD322WORD16(0x5a82799a) +#endif +#define MDCT_MEM_LEN_MAX (MAX_LEN - ((180 * MAX_LEN) / 480)) + +/* TNS */ +#define TNS_NUMFILTERS_MAX 2 +#define TNS_COEF_RES 17 +#define INDEX_SHIFT 8 +#define NSUBDIV 3 +#define MAXLAG 8 + +/* OLPA/LTPF */ +#define LEN_12K8 128 +#define LEN_6K4 64 +#define MIN_PITCH_6K4 17 +#define MAX_PITCH_6K4 114 +#define RANGE_PITCH_6K4 98 +#define MIN_PITCH_12K8 32 +#define MAX_PITCH_12K8 228 +#define RES2_PITCH_12K8 157 +#define RES4_PITCH_12K8 127 +#define LTPF_MEMIN_LEN (MAX_PITCH_12K8 + 4) +#define M_LTPF 24 +#define LTPF_MEM_X_LEN (MAX_LEN + MAX_LEN / 40 - 2) +#define LTPF_MEM_Y_LEN (MAX_LEN + CEILING(MAX_PITCH_12K8 * MAX_LEN, 128) + (MAX_LEN / 80)) + +/* PLC */ +#ifdef CR9_I_INC_TDC_FADEOUT_LEN +# define PLC_FADEOUT_TYPE_1_IN_MS 200 +#endif +#define PLC_FADEOUT_IN_MS 60 /* fade-out to zero in ms for TD-PLC and NS, minimum value is 20 */ + +# ifdef CR8_A_PLC_FADEOUT_TUNING + /* table settings */ +# define PLC2_FADEOUT_IN_MS_MIN 30 /* table min */ +# define PLC2_FADEOUT_IN_MS_MAX 140 /* table max */ +# define PLC2_FADEOUT_RES 10 /* 10 ms steps used in fade tables */ + +/* current settings */ +# define PLC2_FADEOUT_LONG_IN_MS 120 +# define PLC2_FADEOUT_IN_MS 30 /* 0 uses original constants for PLC2 + -1 uses TDC::PLC_FADEOUT_IN_MS as basis for a PLC2 macro-re-calculation + 30..140 will use a separate settings for PLC2 fadeout + 30: P800 short fade optimization + 120: Mushra optimized fade */ +#else +# define PLC2_FADEOUT_IN_MS 30 /* 0 uses original fixed values for PLC2 + -1 uses PLC_FADEOUT_IN_MS as basis for a PLC2 macro-re-calculation + 30..100 uses separate setting for PLC2 */ +#endif + + + +#define PLC4_TRANSIT_END_IN_MS PLC_FADEOUT_IN_MS /* end of transition time for noise substitution */ +#define PLC4_TRANSIT_START_IN_MS 20 /* begin of transition time for noise substitution for voiced signals */ +#define PLC34_ATTEN_FAC_100_FX 0x4000 /* attenuation factor for NS and TDC @ 10 ms (0.5000)*/ +#define PLC34_ATTEN_FAC_050_FX 0x5A83 /* attenuation factor for NS and TDC @ 5.0 ms (0.7071)*/ +#define PLC34_ATTEN_FAC_025_FX 0x6BA3 /* attenuation factor for NS and TDC @ 2.5 ms (0.8409)*/ +#ifdef CR8_G_ADD_75MS +#define PLC34_ATTEN_FAC_075_FX 0x4C1C /* attenuation factor for NS and TDC @ 7.5 ms (0.5946) */ +#endif +#define PLC3_HPBLENDTHROTTLE 30 /* higher numbers increase throttled blending from hp filtered to unfiltered uv excitation (0 is no throttle) */ + +#define MAX_PITCH_8K (CEILING((MAX_PITCH_12K8 * 8000), (12800))) /*NB was a risky MACRO at 0.5 border !!, */ +#define MAX_PITCH_16K ((MAX_PITCH_12K8 * 16000) / (12800)) /* exact integer */ +#define MAX_PITCH_24K \ + (CEILING((MAX_PITCH_12K8 * 24000), (12800))) /* was a risky MACRO truncation at 0.5 border !! , */ +#define MAX_PITCH_32K ((MAX_PITCH_12K8 * 32000) / (12800)) /* exact integer */ +#define MAX_PITCH_48K ((MAX_PITCH_12K8 * 48000) / (12800)) /* exact integer */ + +#ifdef ENABLE_HR_MODE +# define MAX_PITCH_96K ((MAX_PITCH_12K8 * 96000) / (12800)) /* exact integer */ +#endif + +#ifdef ENABLE_HR_MODE +# define MAX_PITCH MAX_PITCH_96K +#elif defined(SUBSET_FB) +# define MAX_PITCH MAX_PITCH_48K +#elif defined(SUBSET_SWB) +# define MAX_PITCH MAX_PITCH_32K +#elif defined(SUBSET_SSWB) +# define MAX_PITCH MAX_PITCH_24K +#elif defined(SUBSET_WB) +# define MAX_PITCH MAX_PITCH_16K +#elif defined(SUBSET_NB) +# define MAX_PITCH MAX_PITCH_8K +#endif + + +/* macri MAX_LEN_PCM_PLC is used for WC memory size checking + DYN_MAX_LEN_PCM_PLC(fs) is used by static memory buffers + */ +#define MAX_LEN_PCM_PLC (MAX_PITCH + MAX_LEN) + +#define TDC_L_FIR_HP 11 +#define TDC_L_FIR_LP 11 + +#define BASE_LPROT 512 /* BASE Lprot set to 512 for 32 kHz sampling */ + +#define LPROT48K (BASE_LPROT * 48 / 32) /* Fs based Lprot */ +#define LPROT40K (BASE_LPROT * 40 / 32) /* For Fs == 48000 only use 0 - 20000 Hz in 8 bands */ +#define LPROT32K BASE_LPROT +#define LPROT24K (BASE_LPROT * 24 / 32) +#define LPROT16K (BASE_LPROT * 16 / 32) +#define LPROT8K (BASE_LPROT * 8 / 32) + +/* #define PHECU_XFP_LA 1 */ /* Original soluiton xfp generated with 1ms look ahead into MDCT memory + ctrl.PhECU.LA = 0.001 * ctrl.fs; */ +/* #define PHECU_XFP_LA 4 */ /* Option with some lookahead 1/4 ms look ahead into MDCT memory + ctrl.PhECU.LA = 0.001 * ctrl.fs / 4; */ +#define PHECU_XFP_LA \ + 0 /* Option without lookahead 0 ms look ahead into MDCT memory \ + ctrl.PhECU.LA = 0; */ + +#if (PHECU_XFP_LA == 0) + +# define PHECU_LA_48K 0 /* 0 ms */ +# define PHECU_LA_32K 0 /* 0 ms */ +# define PHECU_LA_24K 0 /* 0 ms */ +# define PHECU_LA_16K 0 /* 0 ms */ +# define PHECU_LA_8K 0 /* 0 ms */ + +# define MAX_PHECU_LA (0) + +#else +# if (PHECU_XFP_LA == 4) + +# define PHECU_LA_48K (48 / 4) /* 0.25 ms */ +# define PHECU_LA_32K (32 / 4) /* 0.25 ms */ +# define PHECU_LA_24K (24 / 4) /* 0.25 ms */ +# define PHECU_LA_16K (16 / 4) /* 0.25 ms */ +# define PHECU_LA_8K (8 / 4) /* 0.25 ms */ + +# define MAX_PHECU_LA (MAX_LEN / 10 / 4) + +# else + +# define PHECU_LA_48K 48 /* 1 ms */ +# define PHECU_LA_32K 32 /* 1 ms */ +# define PHECU_LA_24K 24 /* 1 ms */ +# define PHECU_LA_16K 16 /* 1 ms */ +# define PHECU_LA_8K 8 /* 1 ms */ + +# define MAX_PHECU_LA (MAX_LEN / 10) + +# endif +#endif + + +/* (PHECU_LA_48K == 0) */ + +#define COPY_LEN_8K 16 +#define COPY_LEN_16K 32 +#define COPY_LEN_24K 48 +#define COPY_LEN_32K 64 +#define COPY_LEN_48K 96 + +#define OLA_LEN_8K 14 +#define OLA_LEN_16K 28 +#define OLA_LEN_24K 42 +#define OLA_LEN_32K 56 +#define OLA_LEN_48K 84 + +#define LPROT48K_RED LPROT40K /* limit peak searched part of spectrum for FB */ +#define LPROT32K_RED LPROT32K /* limit peak searched part of spectrum for SWB */ +#define LPROT24K_RED LPROT24K /* limit peak searched part of spectrum for HQ */ +#define LPROT16K_RED LPROT16K /* limit peak searched part of spectrum for SQ */ +#define LPROT8K_RED LPROT8K /* limit peak searched part of spectrum for NB */ + +#define INV_LPROT48K_Q22 5461 /* round(2^22/LPROT48K) , 1/6 */ +#define INV_LPROT32K_Q22 8192 /* round(2^22/LPROT32K) , 1/4 */ +#define INV_LPROT24K_Q22 10923 /* round(2^22/LPROT24K) , 1/3 */ +#define INV_LPROT16K_Q22 16384 /* round(2^22/LPROT16K) , 1/2 */ +#define INV_LPROT8K_Q22 32767 /* round(2^22/LPROT8K) , 1/1 */ + +#define LGW48K 8 /* 8 bands defined , but may the same frequency groups as for SWB(32k) */ +#define LGW32K 7 +#define LGW24K 6 +#define LGW16K 5 +#define LGW8K 4 + +#define MAX_LGW 9 /* LGW48K + 1 !! */ + +#define UNINIT_OR_UNSAFE_OOLD_SENTINEL -32768 +#define LTOT_INIT_FLAG -32768 +#define LTOT_MIN_MAN 1 /* lowest possible energy value */ +#define LTOT_MIN_EXP -61 /* L_tot= LTOT_MIN_MAN*2^(LTOT_MIN_EXP-31) */ +#define GRP_SHAPE_INIT 0 /* Q15 */ + +#define TRANA_TIME 4 /* Transient analysis length in ms */ +#define LTRANA48K (48000 * TRANA_TIME / 1000) +#define LTRANA32K (32000 * TRANA_TIME / 1000) +#define LTRANA24K (24000 * TRANA_TIME / 1000) +#define LTRANA16K (16000 * TRANA_TIME / 1000) +#define LTRANA8K (8000 * TRANA_TIME / 1000) + +#define MAX_PLOCS ((MAX_LPROT / 4) + 1) /* maximum number of spectral peaks to be searched */ +#define QUOT_LPR_LTR 4 + +#define BETA_MUTE_FAC_INI 16384 /* Q15, initial noise attenuation factor */ + +#define OFF_FRAMES_LIMIT 30 /* Hard limit to a maximum of 300ms of burst decay frames */ + +#define Lprot_hamm_len2_48k (3 * 48) +#define Lprot_hamm_len2_32k (3 * 32) +#define Lprot_hamm_len2_24k (3 * 24) +#define Lprot_hamm_len2_16k (3 * 16) +#define Lprot_hamm_len2_8k (3 * 8) + +#define FRAME_TIME 10 /* Frame length in ms */ + +#define L_FRAME48K (48000 * FRAME_TIME / 1000) +#define L_FRAME32K (32000 * FRAME_TIME / 1000) +#define L_FRAME24K (24000 * FRAME_TIME / 1000) +#define L_FRAME16K (16000 * FRAME_TIME / 1000) +#define L_FRAME8K (8000 * FRAME_TIME / 1000) + +#ifdef DISABLE_PLC +# define MAX_LTRANA 0 +# define MAX_LPROT LPROT48K +# define MAX_L_FRAME L_FRAME48K +# define MAX_LPROT_RED LPROT48K_RED +#else + +# ifdef SUBSET_UB +# define MAX_LPROT LPROT48K /* Max length of protype frame for buffer allocation */ +# define MAX_LPROT_RED LPROT48K_RED /* stack alloc peak searched part */ +# define MAX_LTRANA LTRANA48K +# define MAX_L_FRAME L_FRAME48K +# elif defined(SUBSET_FB) +# define MAX_LPROT LPROT48K /* Max length of protype frame for buffer allocation */ +# define MAX_LPROT_RED LPROT48K_RED /* stack alloc peak searched part */ +# define MAX_LTRANA LTRANA48K +# define MAX_L_FRAME L_FRAME48K +# elif defined(SUBSET_SWB) +# define MAX_LPROT LPROT32K +# define MAX_LPROT_RED LPROT32K_RED /* stack alloc peak searched part */ +# define MAX_LTRANA LTRANA32K +# define MAX_L_FRAME L_FRAME32K +# elif defined(SUBSET_SSWB) +# define MAX_LPROT LPROT24K +# define MAX_LPROT_RED LPROT24K_RED /* stack alloc peak searched part */ +# define MAX_LTRANA LTRANA24K +# define MAX_L_FRAME L_FRAME24K +# elif defined(SUBSET_WB) +# define MAX_LPROT LPROT16K +# define MAX_LPROT_RED LPROT16K_RED /* stack alloc peak searched part */ +# define MAX_LTRANA LTRANA16K +# define MAX_L_FRAME L_FRAME16K +# elif defined(SUBSET_NB) +# define MAX_LPROT LPROT8K +# define MAX_LPROT_RED LPROT8K_RED /* stack alloc peak searched part */ +# define MAX_LTRANA LTRANA8K +# define MAX_L_FRAME L_FRAME8K +# endif + +#endif /* #ifdef DISABLE_PLC */ + +#define INV_L_FRAME48K_Q15 32768 / L_FRAME48K +#define INV_L_FRAME32K_Q15 32768 / L_FRAME32K +#define INV_L_FRAME24K_Q15 32768 / L_FRAME24K +#define INV_L_FRAME16K_Q15 32768 / L_FRAME16K +#define INV_L_FRAME8K_Q15 32768 / L_FRAME8K + +#define MDCT_MEM_LEN_48 (L_FRAME48K - ((180 * L_FRAME48K) / 480)) + +#define R1_48 690 +#define R2_48 420 +#define R1_16 230 +#define R2_16 140 +#define R1_25 368 +#define R2_25 224 + +#define MAX_LEN_PCM_PLC_TOT (MAX_LEN_PCM_PLC) /* TDC_pcm_buff */ +#define MAX_WIN_PRE_TDA (0) /* not in RAM any longer , now stored in ROM only as PhECU_wins[fs_idx][1] */ + +#define MAX_PLCMETH 1 + +/* Scratch buffer defines */ +#define scratchBuffer_ACTIVE +#ifdef ENABLE_HR_MODE +# define SCRATCH_BUF_LEN_ENC (4 * MAX_LEN + 32 + 32 + 4 * MAX_LEN + 3 * MAX_LEN + MAX_RESBITS_LEN_32BIT_ALIGN) +# define SCRATCH_BUF_LEN_ENC_CURRENT_SCRATCH (4 * MAX_LEN + 8 * 60 + MAX_LEN) +#else +# define SCRATCH_BUF_LEN_ENC (4 * MAX_LEN + 32 + 32 + 2 * MAX_LEN + 3 * MAX_LEN + MAX_RESBITS_LEN_32BIT_ALIGN) +# define SCRATCH_BUF_LEN_ENC_CURRENT_SCRATCH (4 * MAX_LEN) +#endif + +#define SCRATCH_BUF_LEN_ENC_TOT (SCRATCH_BUF_LEN_ENC + SCRATCH_BUF_LEN_ENC_CURRENT_SCRATCH) + +#ifdef ENABLE_HR_MODE +# define SCRATCH_BUF_LEN_DEC (4 * MAX_LEN + MAX_RESBITS_LEN_32BIT_ALIGN + 32 + 32 + 4 * MAX_LEN + 32 + 128 + 128) +#else +# define SCRATCH_BUF_LEN_DEC (4 * MAX_LEN + 2 * MAX_LEN + 32 + 32 + 2 * MAX_LEN + 32 + 128 + 128) +#endif +#define SCRATCH_BUF_LEN_DEC_CURRENT_SCRATCH (2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME) +#ifdef ENABLE_HR_MODE +# define SCRATCH_BUF_LEN_DEC_TOT (SCRATCH_BUF_LEN_DEC + (4 * HR_MODE_SCRATCH_SIZE) + SCRATCH_BUF_LEN_DEC_CURRENT_SCRATCH) +#else +# define SCRATCH_BUF_LEN_DEC_TOT (SCRATCH_BUF_LEN_DEC + SCRATCH_BUF_LEN_DEC_CURRENT_SCRATCH) +#endif + +#define ADVACED_PLC_SIZE \ + (sizeof(AplcSetup) + (4 + 2) * MAX_PLOCS + 2 * MAX_LEN_PCM_PLC_TOT + 0 * MAX_LPROT + 2 * MDCT_MEM_LEN_MAX + \ + 2 * MAX_WIN_PRE_TDA) +/* ERI : Correct this sum after ROM/RAM , joint RAM optimizations */ + + +#define ENC_MAX_SIZE (sizeof(LC3PLUS_Enc) + MAX_CHANNELS * (sizeof(EncSetup) + 6 * MDCT_MEM_LEN_MAX)) +#define DEC_MAX_SIZE \ + (sizeof(LC3PLUS_Dec) + MAX_CHANNELS * (sizeof(DecSetup) + ADVACED_PLC_SIZE + 2 * LTPF_MEM_X_LEN + 2 * LTPF_MEM_Y_LEN + \ + 2 * MDCT_MEM_LEN_MAX + 2 * MAX_BW)) + +#if (defined(_M_ARM) || defined(__CC_ARM) || defined(__TMS470__) || defined(__arm__) || defined(__aarch64__)) && \ + (defined(__TARGET_FEATURE_NEON) || defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__ARM_AARCH64_NEON__)) +# define ALIGNMENT_DEFAULT 16 +#elif defined(__bfin__) +# define ALIGNMENT_DEFAULT 4 +#else +# define ALIGNMENT_DEFAULT 8 +#endif + +/* RAM_ALIGN keyword causes memory alignment of global variables. */ +#if defined(__GNUC__) +# define RAM_ALIGN __attribute__((aligned(ALIGNMENT_DEFAULT))) +#elif defined(__CC_ARM) +# define RAM_ALIGN __align(ALIGNMENT_DEFAULT) +#elif defined(__ANALOG_EXTENSIONS__) +# define RAM_ALIGN +# pragma pack(ALIGNMENT_DEFAULT) +#elif defined(_MSC_VER) +# define RAM_ALIGN __declspec(align(ALIGNMENT_DEFAULT)) +#else +# define RAM_ALIGN +#endif + +#define scratchAlign(ptr, offset) (void *)(((uintptr_t)(ptr) + (offset) + 0x3) & ~0x3) +#define ALIGN_BUFFER_STRUCT + + +/* some configurations leave empty translation units. */ +extern int fix_empty_translation_unit_warning; + +#endif diff --git a/lib_lc3plus/detect_cutoff_warped_fx.c b/lib_lc3plus/detect_cutoff_warped_fx.c new file mode 100644 index 000000000..b6ef25472 --- /dev/null +++ b/lib_lc3plus/detect_cutoff_warped_fx.c @@ -0,0 +1,124 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include "rom_basop_util.h" + +void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 frame_dms) +{ + + Dyn_Mem_Deluxe_In( + Counter iBand; + Word32 d2_fx_sum; + Word32 d2_fx_mean; + Word32 delta_energy; + Word16 d2_fx_sum_exp; + Word16 d2_fx_mean_exp; + Word16 nrg_below_thresh; + Word16 counter; + Word16 brickwall; + Word16 stop; + Word16 brickwall_dist; + const Word16 *warp_idx_start, *warp_idx_stop, *bw_brickwall_dist; + ); + + SWITCH (frame_dms) + { + case 25: + warp_idx_start = BW_warp_idx_start_all_2_5ms[fs_idx - 1]; move16(); + warp_idx_stop = BW_warp_idx_stop_all_2_5ms[fs_idx - 1]; move16(); + bw_brickwall_dist = BW_brickwall_dist_2_5ms; + BREAK; + case 50: + warp_idx_start = BW_warp_idx_start_all_5ms[fs_idx - 1]; move16(); + warp_idx_stop = BW_warp_idx_stop_all_5ms[fs_idx - 1]; move16(); + bw_brickwall_dist = BW_brickwall_dist_5ms; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + warp_idx_start = BW_warp_idx_start_all_7_5ms[fs_idx - 1]; move16(); + warp_idx_stop = BW_warp_idx_stop_all_7_5ms[fs_idx - 1]; move16(); + bw_brickwall_dist = BW_brickwall_dist_7_5ms; + BREAK; +#endif + default: /* 100 */ + warp_idx_start = BW_warp_idx_start_all[fs_idx - 1]; move16(); + warp_idx_stop = BW_warp_idx_stop_all[fs_idx - 1]; move16(); + bw_brickwall_dist = BW_brickwall_dist; + BREAK; + } + + counter = fs_idx; + DO + { + + /* counter is 0...num_idxs-1 */ + counter = sub(counter, 1); + + /* always code the lowest band (NB), skip check against threshold if counter == -1 */ + IF (counter < 0) + { + BREAK; + } + + d2_fx_mean = 0; move32(); + d2_fx_mean_exp = 0; move16(); + + iBand = warp_idx_start[counter]; move16(); + d2_fx_sum = d2_fx[iBand]; move32(); + d2_fx_sum_exp = d2_fx_exp; move16(); + + iBand++; + FOR (; iBand <= warp_idx_stop[counter]; iBand++) + { + d2_fx_sum = BASOP_Util_Add_Mant32Exp_lc3plus(d2_fx[iBand], d2_fx_exp, d2_fx_sum, d2_fx_sum_exp, &d2_fx_sum_exp); + } + /* Energy-sum */ + d2_fx_mean = Mpy_32_16_lc3plus(d2_fx_sum, InvIntTable[add(sub(warp_idx_stop[counter], warp_idx_start[counter]), 1)]); + d2_fx_mean_exp = d2_fx_sum_exp; move16(); + + /* check if above threshold */ + nrg_below_thresh = BASOP_Util_Cmp_Mant32Exp_lc3plus(BW_thresh_quiet[counter], BW_thresh_quiet_exp, d2_fx_mean, + d2_fx_mean_exp); /* true if firstNumber > secondNumber */ + } + WHILE (nrg_below_thresh > 0) + ; + + *bw_idx = add(1, counter); move16(); + + /* addtional check for brickwall characteristic */ + IF (sub(fs_idx, *bw_idx) > 0) + { + brickwall = 0; move16(); + stop = add(warp_idx_start[counter + 1], 1); + brickwall_dist = bw_brickwall_dist[counter + 1]; + + FOR (iBand = stop; iBand >= sub(stop, brickwall_dist); iBand--) + { + /* Band(x) > Band(x-3)*Thr */ + delta_energy = + L_sub(Mpy_32_16_lc3plus(d2_fx[iBand - brickwall_dist], BW_thresh_brickwall[counter + 1]), d2_fx[iBand]); + if (delta_energy > 0) + { + brickwall = 1; move16(); + } + IF (brickwall) + { + BREAK; + } + } + if (brickwall == 0) + { + *bw_idx = fs_idx; + } + } + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/dynmem.c b/lib_lc3plus/dynmem.c new file mode 100644 index 000000000..65e157d0a --- /dev/null +++ b/lib_lc3plus/dynmem.c @@ -0,0 +1,288 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + + +/* + Tool for dynamic memory estimation + Anisse Taleb, November 2003 + +*/ + +/* turn off stdlib function warnings in visual studio */ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include +#include + +#include "dynmem.h" + +#define MAX_FUNC_NAME_LENGTH 128 + + + +struct C_Path{ + char func_name[MAX_FUNC_NAME_LENGTH]; + long mem_usage; + long mem_usage_acc; + struct C_Path *next; + struct C_Path *parent; +}; + + +typedef struct C_Path C_Path; + +static C_Path *Max_Mem_path; /* Snap shot of the maximum memory usage path */ +static C_Path *Head_path; +static C_Path *Curr_path; /* Current code path */ + + +static long Max_mem_usage; + +static C_Path *Static_mem_head; +static C_Path *Static_mem_curr; + +/* + * initialisation. Must be called at start, sets up all the + * structures and resets counters. + * + * Called externally. + */ + +static void path_free(C_Path * path) +{ + C_Path *path_end,*tmp; + path_end = path; + + if(path == NULL) return; + /* find last node */ + while(path_end->next != NULL) path_end = path_end->next; + + /* walk back */ + while(path_end != NULL) { + tmp = path_end; + path_end = path_end->parent; + free(tmp); + } + +} +static void path_save(void) +{ + C_Path * node; + C_Path * node_save; + C_Path * previous; + /* free the old path */ + path_free(Max_Mem_path); + Max_Mem_path = NULL; + /* */ + + Max_Mem_path = (C_Path *) malloc(sizeof(C_Path)); + + node = Head_path; + node_save = Max_Mem_path; + previous = NULL; + while(node != NULL){ + + strcpy(node_save->func_name,node->func_name); + node_save->mem_usage = node->mem_usage; + node_save->mem_usage_acc = node->mem_usage_acc; + + node_save->parent = previous; + node_save->next = NULL; + + if(node->next != NULL) { + node_save->next = (C_Path *) malloc(sizeof(C_Path)); + } + node = node->next; + previous = node_save; + node_save = node_save->next; + } while(node != NULL); + +} + +void P_Dyn_Mem_Init(void) +{ + + /* initialize the path */ + Head_path = (C_Path *) malloc(sizeof(C_Path)); + strcpy(Head_path->func_name,"---Top---"); + Head_path->mem_usage = 0; + Head_path->mem_usage_acc = 0; /*memory usage accumulator */ + Head_path->parent = NULL; + Head_path->next = NULL; + + Curr_path = Head_path; + /* Initilaize the memory consumptions */ + Max_mem_usage = 0; + Max_Mem_path = NULL; +} + +void P_Dyn_Mem_In(const char *func_name, + long mem_usage) +{ +#ifdef DEBUG_DYNMEM + printf( "Entering: %s\n", func_name ); +#endif + + /* Enter a new function, push on the stack */ + if(Curr_path->next != NULL) { + fprintf(stderr,"\n Something went wrong !!"); + exit(0); + + } + Curr_path->next = (C_Path*) malloc (sizeof(C_Path)); + + if(Curr_path->next == NULL) { + fprintf(stderr,"\n Can't allocate memory"); + exit(0); + } + + Curr_path->next->parent = Curr_path; + Curr_path = Curr_path->next; + Curr_path->next = NULL; + /* save function name */ + strcpy(Curr_path->func_name,func_name); + /* save memory usage */ + Curr_path->mem_usage = mem_usage; + /* update memory usage accumulator */ + Curr_path->mem_usage_acc = Curr_path->parent->mem_usage_acc + mem_usage; +} + +/* Add memory size to current function */ +void P_Dyn_Mem_Add(long mem_usage) +{ +#ifdef DEBUG_DYNMEM + printf( "Staying in: %s\n", Curr_path->func_name); +#endif + + /* Staying in the current function, nothing to push */ + + /* save memory usage */ + Curr_path->mem_usage = Curr_path->mem_usage + mem_usage; + /* update memory usage accumulator */ + Curr_path->mem_usage_acc = Curr_path->mem_usage_acc + mem_usage; +} + + +/* before any return */ + +void P_Dyn_Mem_Out(void) +{ + C_Path *tmp; + if(Curr_path->mem_usage_acc > Max_mem_usage) { + /* set new memory usage record */ + Max_mem_usage = Curr_path->mem_usage_acc; + /* save snap shot */ + path_save(); + } + +#ifdef DEBUG_DYNMEM + printf( "Exiting: %s\n", Curr_path->func_name ); +#endif + + /* delete last node */ + tmp = Curr_path; + + Curr_path = Curr_path->parent; + Curr_path->next = NULL; + free(tmp); +} + + +/* Write data and exit */ + +void P_Dyn_Mem_Exit(void) +{ + /*FILE *f_mem_statistics;*/ + C_Path *node; + /*f_mem_statistics = fopen("mem_stat.txt","wt"); + fprintf(f_mem_statistics,"\n Maximum dynamic memory usage = %ld b, %ld kW \n Critical Memory Usage Path", Max_mem_usage, Max_mem_usage/(1000*2));*/ + /* fprintf(stderr,"\n Maximum dynamic memory usage = %ld kWords (%ld bytes)\n Critical Memory Usage Path", Max_mem_usage/(1000*2),Max_mem_usage); */ + fprintf(stderr,"\n Maximum dynamic memory usage = %.2f kWords (%ld bytes)\n Critical Memory Usage Path", (ceil((float)Max_mem_usage/20.f)/100.f), Max_mem_usage); + + node = Max_Mem_path; + while (node != NULL) { + /*fprintf(f_mem_statistics,"\n %-30s %10ld bytes (+ %10ld bytes)",node->func_name, node->mem_usage_acc, node->mem_usage);*/ + fprintf(stderr,"\n %-30s %10ld bytes (+ %10ld bytes)",node->func_name, node->mem_usage_acc, node->mem_usage); + node=node->next; + } + + /*fclose(f_mem_statistics);*/ + fprintf(stderr,"\n"); + +#ifdef CTEST_MEASUREMENTS + printf("%.3f\n", "dynMem [kWords]", "numeric/float", Max_mem_usage/(1000.0*2)); +#endif + + path_free(Max_Mem_path); + path_free(Head_path); +} + +void P_Dyn_Mem_Exit_noprint(void) +{ + path_free(Max_Mem_path); + path_free(Head_path); +} +void P_Sta_Mem_Init(void) +{ + /* initialize the head object */ + Static_mem_head = (C_Path *) malloc(sizeof(C_Path)); + strcpy(Static_mem_head->func_name,"---Top---"); + Static_mem_head->mem_usage = 0; + Static_mem_head->mem_usage_acc = 0; + Static_mem_head->parent = NULL; + Static_mem_head->next = NULL; + Static_mem_curr = Static_mem_head; +} + +void P_Sta_Mem_Add(const char *func_name, + long mem_usage) +{ + /* Enter a new function, push on the stack */ + Static_mem_curr->next = (C_Path*) malloc (sizeof(C_Path)); + Static_mem_curr->next->parent = Static_mem_curr; + Static_mem_curr = Static_mem_curr->next; + Static_mem_curr->next = NULL; + /* save function name */ + strcpy(Static_mem_curr->func_name,func_name); + /* save memory usage */ + Static_mem_curr->mem_usage = mem_usage; + /* update memory usage accumulator */ + Static_mem_curr->mem_usage_acc = Static_mem_curr->parent->mem_usage_acc + mem_usage; +} + +void P_Sta_Mem_Exit(void) +{ + C_Path *node; + /* fprintf(stderr,"\n Static memory usage = %ld kWords (%ld bytes)\n Detailed Memory Usage", Static_mem_curr->mem_usage_acc/(1000*2),Static_mem_curr->mem_usage_acc); */ + fprintf(stderr,"\n Static memory usage = %.2f kWords (%ld bytes)\n Detailed Memory Usage", (ceil((float)Static_mem_curr->mem_usage_acc/20.f)/100.f),Static_mem_curr->mem_usage_acc); + + node = Static_mem_head->next; + while (node != NULL) { + fprintf(stderr,"\n %-30s %10ld bytes (+ %10ld bytes)",node->func_name, node->mem_usage_acc, node->mem_usage); + node=node->next; + } + + fprintf(stderr,"\n"); + +#ifdef CTEST_MEASUREMENTS + printf("%.3f\n", "statMem [kWords]", "numeric/float", Static_mem_curr->mem_usage_acc/(1000.0*2)); +#endif + + path_free(Static_mem_head); +} + +void P_Sta_Mem_Exit_noprint(void) +{ + path_free(Static_mem_head); +} diff --git a/lib_lc3plus/dynmem.h b/lib_lc3plus/dynmem.h new file mode 100644 index 000000000..e81169a33 --- /dev/null +++ b/lib_lc3plus/dynmem.h @@ -0,0 +1,80 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + + +#ifndef DYNMEM_H +#define DYNMEM_H + +#ifdef _MSC_VER +/* This disables warnings about anonymous temporary struct declarations */ +#pragma warning(disable:4115) +#pragma warning(disable:4116) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void P_Dyn_Mem_Init(void); +void P_Dyn_Mem_In(const char *func_name, + long mem_usage); +void P_Dyn_Mem_Add(long mem_usage); +void P_Dyn_Mem_Out(void); +void P_Dyn_Mem_Exit(void); +void P_Dyn_Mem_Exit_noprint(void); + +void P_Sta_Mem_Init(void); +void P_Sta_Mem_Add(const char *func_name, + long mem_usage); +void P_Sta_Mem_Exit(void); +void P_Sta_Mem_Exit_noprint(void); + +#ifdef DONT_COUNT_MEM + +#define Dyn_Mem_Init() +#define Dyn_Mem_Exit() +#define Dyn_Mem_Exit_noprint() +#define Dyn_Mem_In(a,b) +#define Dyn_Mem_Add(b) +#define Dyn_Mem_Out() + +#define DYN_MEM_IN Dyn_Mem_In +#define DYN_MEM_ADD Dyn_Mem_Add +#define DYN_MEM_OUT Dyn_Mem_Out + +#define Sta_Mem_Init() +#define Sta_Mem_Exit() +#define Sta_Mem_Exit_noprint() +#define Sta_Mem_Add(a,b) + +#else /* DONT_COUNT_MEM */ + +#define Dyn_Mem_Init P_Dyn_Mem_Init +#define Dyn_Mem_Exit P_Dyn_Mem_Exit +#define Dyn_Mem_Exit_noprint P_Dyn_Mem_Exit_noprint +#define Dyn_Mem_In P_Dyn_Mem_In +#define Dyn_Mem_Add P_Dyn_Mem_Add +#define Dyn_Mem_Out P_Dyn_Mem_Out + +#define DYN_MEM_IN P_Dyn_Mem_In +#define DYN_MEM_ADD P_Dyn_Mem_Add +#define DYN_MEM_OUT P_Dyn_Mem_Out + +#define Sta_Mem_Init P_Sta_Mem_Init +#define Sta_Mem_Exit P_Sta_Mem_Exit +#define Sta_Mem_Exit_noprint P_Sta_Mem_Exit_noprint +#define Sta_Mem_Add P_Sta_Mem_Add + +#endif /* DONT_COUNT_MEM */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib_lc3plus/enc_entropy.c b/lib_lc3plus/enc_entropy.c new file mode 100644 index 000000000..35dd8d950 --- /dev/null +++ b/lib_lc3plus/enc_entropy.c @@ -0,0 +1,173 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static Word32 ac_enc_mux_st2VQ_cws( /* o: max 25 bits total codeword */ + const Word32 L_szA, /* i: max 22 bits */ + const Word32 L_szB, /* i: max 4 bits */ + const Word32 L_cwA, const Word32 L_cwB); + +void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 targetBytes, + Word16 L_spec, Word16 BW_cutoff_bits, Word16 tns_numfilters, + Word16 lsbMode, Word16 lastnz, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, + Word16 BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, Word16 bfi_ext, Word16 fs_idx) +{ + Word16 tmp; + Word32 L_tmp; + Word16 submode_LSB, submode_MSB, gain_MSBs; + Word32 L_gain_LSB; + Counter n; + UWord8 *ptr; + + Word16 lastnzTrigger[5] = {63, 127, 127, 255, 255}; + +#ifdef DYNMEM_COUNT + struct _dynmem + { + Word16 tmp; + Word32 L_tmp; + Word16 submode_LSB, submode_MSB, gain_MSBs; + Word32 L_gain_LSB; + Counter n; + UWord8 *ptr; + Word16 lastnzTrigger[5]; + }; + Dyn_Mem_In("processEncoderEntropy", sizeof(struct _dynmem)); +#endif + + /* Init */ + *bp_side = shr_pos(sub(nbbits, 1), 3); + *mask_side = shl(1, sub(8, sub(nbbits, shl_pos(*bp_side, 3)))); + ptr = bytes; + + basop_memset(bytes, 0, targetBytes * sizeof(*bytes)); + + /* Cutoff-detection */ + IF (BW_cutoff_bits > 0) + { + write_indice_backward(ptr, bp_side, mask_side, BW_cutoff_idx, BW_cutoff_bits); + } + + /* Encode last non-zero tuple */ + tmp = sub(14, norm_s(negate(L_spec))); + + IF (sub(bfi_ext, 1) == 0) + { + write_indice_backward(ptr, bp_side, mask_side, lastnzTrigger[fs_idx], tmp); + } + ELSE + { + write_indice_backward(ptr, bp_side, mask_side, sub(shr_pos(lastnz, 1), 1), tmp); + } + + /* Mode bit */ + write_bit_backward(ptr, bp_side, mask_side, lsbMode); + + /* Encode global-gain */ + write_indice_backward(ptr, bp_side, mask_side, gg_idx, 8); + + /* TNS on/off flag */ + FOR (n = 0; n < tns_numfilters; n++) + { + write_bit_backward(ptr, bp_side, mask_side, s_min(tns_order[n], 1)); + } + + /* LTPF on/off*/ + write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[0], 1); + + /* Encode SCF VQ parameters - 1st stage (10 bits) */ + write_indice_backward(ptr, bp_side, mask_side, extract_l(L_scf_idx[0]), 5); /* stage1 LF 5 bits */ + write_indice_backward(ptr, bp_side, mask_side, extract_l(L_scf_idx[1]), 5); /* stage1 HF 5 bits */ + + /* Encode SCF VQ parameters - 2nd stage side-info (3-4 bits) */ + submode_MSB = shr_pos(extract_l(L_scf_idx[2]), 1); /* explicit tx */ + write_bit_backward(ptr, bp_side, mask_side, submode_MSB); /* submode MSB 1 explicit bit */ + submode_LSB = s_and(extract_l(L_scf_idx[2]), 0x1); /* for joint coding with shapeCw */ + gain_MSBs = extract_l(L_scf_idx[3]); /* all gain bits */ + L_gain_LSB = L_and(L_scf_idx[3], 0x1L); + gain_MSBs = shr(gain_MSBs, sns_gainLSBbits[L_scf_idx[2]]); + + ASSERT(gain_MSBs >= 0 && gain_MSBs < (1 << sns_gainMSBbits[L_scf_idx[2]])); /* ASSERT max 2 MSB(s) in gain bits */ + + write_indice_backward(ptr, bp_side, mask_side, gain_MSBs, + sns_gainMSBbits[L_scf_idx[2]]); /* adjgain or MSBs of adjGains 1-2 bits */ + write_bit_backward(ptr, bp_side, mask_side, extract_l(L_scf_idx[4])); /* shape LS 1 bit */ + + /* Encode SCF VQ parameters - 2nd stage data (24-25 bits) */ + IF (submode_MSB == 0) + { /* regular,regular_lf*/ + ASSERT(submode_MSB == 0); + + L_tmp = L_add(L_gain_LSB, 0); /* gain-LSB 0,1 for regular_lf, offset is 0 */ + if (submode_LSB == 0) + { + L_tmp = L_add(L_scf_idx[6], + sns_MPVQ_Sz[1][1]); /* shape B pos offset is 2 , upshifted two positions , 0..11 -> 2..13 */ + } + /* regular mode A,B indexes multiplexed, total 24.x bits MPVQ codeword section A + codeword for section B */ + L_tmp = ac_enc_mux_st2VQ_cws(sns_MPVQ_Sz[0][0], /* max 21.3 bits*/ + UL_addNsD(sns_MPVQ_Sz[0][1], sns_MPVQ_Sz[1][1]), /* max log2(14) bits */ + L_scf_idx[5] /* shapeA */, L_tmp /* shapeB joint with adjGainLSB */); + /* regular mode mode shape index total 1+23.9999 bits MPVQ codeword */ + ASSERT(L_tmp < (1L << 25)); + write_indice_backward(ptr, bp_side, mask_side, extract_l(L_tmp), 13); /* multiplex 13 bits */ + write_indice_backward(ptr, bp_side, mask_side, extract_l(L_shr_pos(L_tmp, 13)), 12); /* multiplex 12 bits */ + } + ELSE + { /* outlier near, outlier far */ + ASSERT(submode_MSB == 1); + L_tmp = L_scf_idx[5]; move32(); /* outlier near section assumed */ + if (submode_LSB != 0) + { /* outl_far */ + L_tmp = L_add(L_shl_pos(L_tmp, 1), L_gain_LSB); /* add lsb bit of Gain */ + L_tmp = L_add(L_tmp, sns_MPVQ_Sz[2][0]); /* outlier far section offset added */ + } + + ASSERT(L_tmp < (1L << 24)); + /* outlier mode shape index total 23.8536 ( + ~.14 ) bits as MPVQ codeword */ + write_indice_backward(ptr, bp_side, mask_side, extract_l(L_tmp), 12); /* multiplex 12 bits LSB*/ + write_indice_backward(ptr, bp_side, mask_side, extract_l(L_shr(L_tmp, 12)), 12); /* multiplex 12 bits MSBs */ + } + + /* LTPF data */ + IF (ltpf_idx[0] != 0) + { + write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[1], 1); + write_indice_backward(ptr, bp_side, mask_side, ltpf_idx[2], 9); + } + + /* Encoder noise-fac */ + write_indice_backward(ptr, bp_side, mask_side, fac_ns_idx, 3); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +static __forceinline Word32 +ac_enc_mux_st2VQ_cws( /* o: max 25 bits total codeword */ + const Word32 L_szA, /* i: max 22 bits */ + const Word32 L_szB, /* i: max 4 bits 0..13 */ + const Word32 L_cwA, + const Word32 L_cwB) /* [0..13} corresponding to gains{0,1}, shapeB{0..11} or */ +{ + + Word32 L_cwTx; + /* L_cw_tx = L_cwB(21.z bits) * L_szA(3.y bits) + L_cwA(21.x bits)); */ + L_cwTx = (Word32)UL_Mpy_32_32( + (UWord32)L_cwB, (UWord32)L_szA); /* non-fractional 16x32 -> 32 may possibly also be used if available */ + L_cwTx = L_add(L_cwTx, L_cwA); + + ASSERT((L_szA * L_szB) <= 1 << 25); /* multiplexing only allowed up to 25 bits (+ leading sign) */ + ASSERT(L_cwTx >= 0 && L_cwTx <= 0x01ffFFff); /* max 25 bits allowed */ + UNUSED(L_szB); + + return L_cwTx; +} diff --git a/lib_lc3plus/enc_lc3.c b/lib_lc3plus/enc_lc3.c new file mode 100644 index 000000000..30ff9971b --- /dev/null +++ b/lib_lc3plus/enc_lc3.c @@ -0,0 +1,680 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include // ToDo: probably to be removed + +static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_sample, Word32 *s_in, UWord8 *bytes, + Word8 *scratchBuffer, int bfi_ext) +{ +#ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In(Word16 d_fx_exp; + Word16 gain_e, gain, quantizedGain, quantizedGainMin; + Word16 ener_fx_exp; + Word16 pitch, normcorr; + Word16 ltpf_bits; + Word16 tns_numfilters; + Word16 lsbMode, lastnz, BW_cutoff_idx; + Word16 gainChange, fac_ns_idx; + Word16 nBits, numResBits; + Word16 bp_side, mask_side; + Word16 s_12k8_len; + Word16 b_left; + Word32 * L_scf_idx; + Word32 * d_fx, *ener_fx; + Word16 * s_12k8, *int_scf_fx_exp, tns_order[TNS_NUMFILTERS_MAX], *indexes; + Word32 * q_d_fx24; + Word16 * scf; + Word16 * codingdata; + Word32 * scf_q, *int_scf_fx; + Word32 * s_in_scaled; + Word16 * s_in_scaled_lp; + UWord8 * resBits; + Word16 ltpf_idx[3]; + EncSetup * h_EncSetup; + Word8 * currentScratch; + Word16 hrmode; + ); +#else + Dyn_Mem_Deluxe_In(Word16 d_fx_exp; Word16 gain_e, gain, quantizedGain, quantizedGainMin; Word16 ener_fx_exp; + Word16 pitch, normcorr; Word16 ltpf_bits; Word16 tns_numfilters; + Word16 lsbMode, lastnz, BW_cutoff_idx; Word16 gainChange, fac_ns_idx; Word16 nBits, numResBits; + Word16 bp_side, mask_side; Word16 s_12k8_len; Word16 b_left; + + Word32 * L_scf_idx; Word32 * d_fx, *ener_fx; + Word16 * s_12k8, *int_scf_fx_exp, *q_d_fx16, *int_scf_fx, tns_order[TNS_NUMFILTERS_MAX], *indexes; + Word16 * scf, *scf_q; Word16 * codingdata; Word16 * s_in_scaled; UWord8 * resBits; + Word8 * currentScratch; Word16 ltpf_idx[3]; EncSetup * h_EncSetup;); +#endif /* ENABLE_HR_MODE */ + + h_EncSetup = encoder->channel_setup[channel]; + +#ifdef ENABLE_HR_MODE +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + hrmode = encoder->hrmode; +# endif +#endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + +#ifdef WMOPS + BASOP_sub_start("Encoder"); +#endif + + /* BUFFER INITIALISATION. Some buffers may overlap since they are not used in the whole encoding process */ + d_fx = scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN bytes */ + L_scf_idx = scratchAlign( + d_fx, sizeof(*d_fx) * s_max(80, encoder->frame_length)); /* Size = 4 * SCF_MAX_PARAM -> aligned to 32 bytes */ + indexes = scratchAlign(L_scf_idx, + sizeof(*L_scf_idx) * SCF_MAX_PARAM); /* Size = 2 * TNS_NUMFILTERS_MAX * MAXLAG = 32 bytes */ + +#ifdef ENABLE_HR_MODE + q_d_fx24 = scratchAlign(indexes, sizeof(*indexes) * (TNS_NUMFILTERS_MAX * MAXLAG)); +#else + q_d_fx16 = scratchAlign(indexes, sizeof(*indexes) * (TNS_NUMFILTERS_MAX * MAXLAG)); /* Size = 2 * MAX_LEN bytes */ +#endif /* ENABLE_HR_MODE */ + +#ifdef ENABLE_HR_MODE + codingdata = + scratchAlign(q_d_fx24, sizeof(*q_d_fx24) * s_max(80, encoder->frame_length)); /* Size = 3 * MAX_LEN bytes */ +#else + codingdata = + scratchAlign(q_d_fx16, sizeof(*q_d_fx16) * s_max(80, encoder->frame_length)); /* Size = 3 * MAX_LEN bytes */ +#endif + +#ifdef ENABLE_HR_MODE + ener_fx = scratchAlign(q_d_fx24, 0); /* Size = 4 * MAX_BANDS_NUMBER = 256 bytes */ + s_in_scaled = scratchAlign(q_d_fx24, 0); /* Size = 2 * MAX_LEN bytes */ +#else + ener_fx = scratchAlign(q_d_fx16, 0); /* Size = 4 * MAX_BANDS_NUMBER = 256 bytes */ + s_in_scaled = scratchAlign(q_d_fx16, 0); /* Size = 2 * MAX_LEN bytes */ +#endif + +#ifdef ENABLE_HR_MODE + s_in_scaled_lp = (Word16 *)s_in_scaled; +#endif + +#ifdef ENABLE_HR_MODE + /* allocate memory for residual bits */ + if (encoder->hrmode) + { + resBits = scratchAlign(codingdata, sizeof(*codingdata) * (3 * s_max(80, encoder->frame_length) / 2)); + } + else +#endif /* #ifdef ENABLE_HR_MODE */ + { + resBits = scratchAlign(codingdata, + sizeof(*codingdata) * (3 * s_max(80, encoder->frame_length) / 2)); /* Size = MAX_LEN bytes */ + } + + { +#ifdef ENABLE_HR_MODE + currentScratch = + scratchAlign(resBits, sizeof(*resBits) * MAX_RESBITS_LEN); /* Size = 4 * MAX_LEN */ +#else + currentScratch = + scratchAlign(resBits, sizeof(*resBits) * s_max(80, encoder->frame_length)); /* Size = 4 * MAX_LEN */ +#endif /* #ifdef ENABLE_HR_MODE */ + } + + s_12k8 = scratchAlign( + s_in_scaled, + sizeof(*s_in_scaled) * + s_max(80, encoder->frame_length)); /* Size = 2 * (LEN_12K8 + 1) = 258 bytes -> aligned to 288 bytes */ + scf_q = scratchAlign(ener_fx, sizeof(*ener_fx) * MAX_BANDS_NUMBER); /* Size = 2 * M */ + scf = scratchAlign(scf_q, sizeof(*scf_q) * M); /* Size = 2 * M */ + int_scf_fx = scratchAlign(scf, sizeof(*scf) * M); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ + int_scf_fx_exp = + scratchAlign(int_scf_fx, sizeof(*int_scf_fx) * MAX_BANDS_NUMBER); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ + + /* Scale 24-bit input data */ + IF (sub(bits_per_sample, 24) == 0) + { +#ifdef WMOPS + BASOP_sub_start("Scale_signal24"); +#endif + scale_signal24_fx(s_in, s_in_scaled, &h_EncSetup->x_exp, h_EncSetup->stEnc_mdct_mem, + encoder->stEnc_mdct_mem_len, h_EncSetup->r12k8_mem_in, encoder->r12k8_mem_in_len, + h_EncSetup->r12k8_mem_50, h_EncSetup->r12k8_mem_out, encoder->r12k8_mem_out_len, + h_EncSetup->mdct_mem32, encoder->frame_length, h_EncSetup->resamp_mem32, + h_EncSetup->olpa_mem_s12k8, &h_EncSetup->resamp_exp); +#ifdef WMOPS + BASOP_sub_end(); +#endif + } + ELSE + { +#ifdef ENABLE_HR_MODE + Word16 *ip_buf = (Word16*)s_in; + Word32 i; + FOR(i = 0; i < encoder->frame_length; i++) + { + s_in_scaled[i] = L_deposit_h(ip_buf[i]); + } + h_EncSetup->x_exp = 15; move16(); +#else + memcpy(s_in_scaled, s_in, encoder->frame_length * sizeof(*s_in_scaled)); +#endif + } + +#ifdef WMOPS + BASOP_sub_start("Mdct"); +#endif + + /* currentScratch Size = 4 * MAX_LEN */ + processMdct_fx(s_in_scaled, h_EncSetup->x_exp, encoder->frame_length, +#ifdef ENABLE_HR_MODE +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + hrmode, +# endif +#endif + encoder->W_fx, encoder->W_size, + h_EncSetup->stEnc_mdct_mem, encoder->stEnc_mdct_mem_len, d_fx, &d_fx_exp, currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + + /* begin s_12k8 */ +#ifdef WMOPS + BASOP_sub_start("Resamp12k8"); +#endif + /* currentScratch Size = 2.25 * MAX_LEN bytes */ +#ifdef ENABLE_HR_MODE + downshift_w32_arr(s_in_scaled, s_in_scaled_lp, 16, encoder->frame_length); /* s_in_scaled is no longer required */ + + process_resamp12k8_fx(s_in_scaled_lp, encoder->frame_length, h_EncSetup->r12k8_mem_in, encoder->r12k8_mem_in_len, + h_EncSetup->r12k8_mem_50, h_EncSetup->r12k8_mem_out, encoder->r12k8_mem_out_len, s_12k8, + &s_12k8_len, encoder->fs_idx, encoder->frame_dms, currentScratch + , bits_per_sample + ); +#else + process_resamp12k8_fx(s_in_scaled, encoder->frame_length, h_EncSetup->r12k8_mem_in, encoder->r12k8_mem_in_len, + h_EncSetup->r12k8_mem_50, h_EncSetup->r12k8_mem_out, encoder->r12k8_mem_out_len, s_12k8, + &s_12k8_len, encoder->fs_idx, encoder->frame_dms, currentScratch + , bits_per_sample + ); +#endif /* ENABLE_HR_MODE */ +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Olpa"); +#endif + /* currentScratch Size = 392 bytes */ + process_olpa_fx(&h_EncSetup->olpa_mem_s6k4_exp, h_EncSetup->olpa_mem_s12k8, h_EncSetup->olpa_mem_s6k4, &pitch, + s_12k8, s_12k8_len, &normcorr, &h_EncSetup->olpa_mem_pitch, +#ifdef CR9_F_PITCH_WIN_LEN_FIX + &h_EncSetup->pitch_flag, +#endif + h_EncSetup->resamp_exp, encoder->frame_dms, currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("LtpfEnc"); +#endif + /* currentScratch Size = 512 bytes */ + process_ltpf_coder_fx(<pf_bits, pitch, h_EncSetup->ltpf_enable, &h_EncSetup->ltpf_mem_in_exp, + h_EncSetup->ltpf_mem_in, encoder->ltpf_mem_in_len, ltpf_idx, s_12k8, s_12k8_len, + &h_EncSetup->ltpf_mem_normcorr, &h_EncSetup->ltpf_mem_mem_normcorr, normcorr, + &h_EncSetup->ltpf_mem_ltpf_on, &h_EncSetup->ltpf_mem_pitch, h_EncSetup->resamp_exp, + encoder->frame_dms, currentScratch +#ifdef CR9_K_REDUCE_NORM_CORR_TH + ,encoder->hrmode +#endif +); +#ifdef WMOPS + BASOP_sub_end(); +#endif + + /* end s_12k8 */ +#ifdef WMOPS + BASOP_sub_start("AttackDetector"); +#endif + /* currentScratch Size = ??? bytes */ +#ifdef ENABLE_HR_MODE + attack_detector_fx(encoder, h_EncSetup, s_in_scaled_lp, sub(h_EncSetup->x_exp, 15), currentScratch); +#else + attack_detector_fx(encoder, h_EncSetup, s_in_scaled, sub(h_EncSetup->x_exp, 15), currentScratch); +#endif +#ifdef WMOPS + BASOP_sub_end(); +#endif + + /* begin ener_fx */ +#ifdef WMOPS + BASOP_sub_start("PerBandEnergy"); +#endif + /* currentScratch Size = 160 bytes */ + processPerBandEnergy_fx(ener_fx, &ener_fx_exp, d_fx, d_fx_exp, encoder->bands_offset, encoder->fs_idx, + encoder->bands_number, 0, encoder->frame_dms, currentScratch +#ifdef ENABLE_HR_MODE + , encoder->hrmode +#endif + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Near Nyquist Detector"); +#endif + /* Near Nyquist Detector */ + processNearNyquistdetector_fx(&encoder->near_nyquist_flag, encoder->fs_idx, encoder->near_nyquist_index, + encoder->bands_number, ener_fx, ener_fx_exp +#ifdef CR8_E_TONE_DETECTOR +#ifdef ENABLE_HR_MODE + , encoder->frame_dms, encoder->hrmode ); +#else + ); +#endif +#else + ); +#endif + /* Disable LTPF if nyquist detector triggers */ + IF (encoder->near_nyquist_flag != 0 || sub(h_EncSetup->lfe, 1) == 0) + { + h_EncSetup->ltpf_mem_ltpf_on = 0; move16(); + ltpf_idx[1] = 0; move16(); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif +#ifdef WMOPS + BASOP_sub_start("BW Cutoff-Detection"); +#endif + IF (h_EncSetup->lfe == 0) + { +#ifdef ENABLE_HR_MODE + /* No BW Cutoff for 8 kHz and 96 kHz */ + IF (encoder->fs_idx > 0 && encoder->hrmode == 0 && encoder->bw_ctrl_active == 0) + { +#else /* ENABLE_HR_MODE */ + IF (encoder->fs_idx > 0 && encoder->bw_ctrl_active == 0) + { +#endif /* ENABLE_HR_MODE */ + processDetectCutoffWarped_fx(&BW_cutoff_idx, ener_fx, ener_fx_exp, encoder->fs_idx, encoder->frame_dms); + } + ELSE + { + BW_cutoff_idx = encoder->fs_idx; + move16(); + } + } + ELSE + { + BW_cutoff_idx = 0; + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("SnsCompScf"); +#endif + + + /* currentScratch Size = 512 bytes */ + processSnsComputeScf_fx(ener_fx, ener_fx_exp, encoder->fs_idx, encoder->bands_number, scf, + h_EncSetup->attdec_detected, encoder->attdec_damping, currentScratch, encoder->sns_damping + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("SnsQuantScfEnc"); +#endif + /* currentScratch Size = 500 bytes */ + + processSnsQuantizeScfEncoder_fx(scf, L_scf_idx, scf_q, currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("SnsInterpScfEnc"); +#endif + /* currentScratch Size = 128 bytes */ + processSnsInterpolateScf_fx(scf_q, int_scf_fx, int_scf_fx_exp, 1, encoder->bands_number, currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Mdct shaping_enc"); +#endif + processMdctShaping_fx(d_fx, int_scf_fx, int_scf_fx_exp, encoder->bands_offset, encoder->bands_number); + +#ifdef WMOPS + BASOP_sub_end(); +#endif + /* end int_scf_fx_exp */ +#ifdef WMOPS + BASOP_sub_start("BandwidthControl_enc"); +#endif + if (encoder->bandwidth < L_shr_pos(encoder->fs, 1)) + { + process_cutoff_bandwidth(d_fx, encoder->yLen, encoder->bw_ctrl_cutoff_bin); + BW_cutoff_idx = s_min(BW_cutoff_idx, encoder->bw_index); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif +#ifdef WMOPS + BASOP_sub_start("Tns_enc"); +#endif + /* currentScratch Size = 2 * MAX_LEN + 220 */ + + IF (h_EncSetup->lfe == 0) + { + processTnsCoder_fx(&(h_EncSetup->tns_bits), indexes, d_fx, BW_cutoff_idx, tns_order, &tns_numfilters, + h_EncSetup->enable_lpc_weighting, encoder->nSubdivisions, encoder->frame_dms, + encoder->frame_length, currentScratch +#ifdef ENABLE_HR_MODE + , encoder->hrmode +#endif + , encoder->near_nyquist_flag + ); + } + ELSE + { + tns_numfilters = 1; + move16(); + tns_order[0] = 0; + move16(); + h_EncSetup->tns_bits = tns_numfilters; + move16(); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Est. Global Gain"); +#endif + /* currentScratch Size = 4 * MAX_LEN bytes */ + h_EncSetup->targetBitsQuant = sub(h_EncSetup->targetBitsInit, add(h_EncSetup->tns_bits, ltpf_bits)); + + test(); + IF (h_EncSetup->targetBitsQuant < 0 && sub(ltpf_bits, 1) > 0) + { + /* Disable LTPF */ + h_EncSetup->ltpf_mem_ltpf_on = 0; move16(); + ltpf_idx[1] = 0; move16(); + ltpf_bits = 1; move16(); + h_EncSetup->targetBitsQuant = sub(h_EncSetup->targetBitsInit, add(h_EncSetup->tns_bits, ltpf_bits)); + } + +#ifdef ENABLE_HR_MODE + Word32 gain32; +#endif + + processEstimateGlobalGain_fx(d_fx, d_fx_exp, encoder->yLen, h_EncSetup->targetBitsQuant, +#ifdef ENABLE_HR_MODE + &gain32, +#else + &gain, +#endif + &gain_e, + &quantizedGain, &quantizedGainMin, h_EncSetup->quantizedGainOff, + &h_EncSetup->targetBitsOff, &h_EncSetup->mem_targetBits, h_EncSetup->mem_specBits, + currentScratch +#ifdef ENABLE_HR_MODE + , encoder->hrmode, h_EncSetup->regBits, encoder->frame_dms +#endif + ); +#ifdef WMOPS + BASOP_sub_end(); +#endif + /* begin q_d_fx16 */ + +#ifdef WMOPS + BASOP_sub_start("Quant. 1"); +#endif +#ifdef ENABLE_HR_MODE + processQuantizeSpec_fx(d_fx, d_fx_exp, gain32, gain_e, q_d_fx24, encoder->yLen, h_EncSetup->targetBitsQuant, + h_EncSetup->targetBitsAri, &h_EncSetup->mem_specBits, &nBits, encoder->fs_idx, &lastnz, + codingdata, &lsbMode, -1, encoder->hrmode); + +#else + processQuantizeSpec_fx(d_fx, d_fx_exp, gain, gain_e, q_d_fx16, encoder->yLen, h_EncSetup->targetBitsQuant, + h_EncSetup->targetBitsAri, &h_EncSetup->mem_specBits, &nBits, encoder->fs_idx, &lastnz, + codingdata, &lsbMode, -1); +#endif /* ENABLE_HR_MODE */ +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Adj. Global Gain"); +#endif +#ifdef ENABLE_HR_MODE + //gain32 = L_shl_pos((Word32)gain, 16); + processAdjustGlobalGain_fx(&quantizedGain, quantizedGainMin, h_EncSetup->quantizedGainOff, &gain32, &gain_e, + h_EncSetup->targetBitsQuant, h_EncSetup->mem_specBits, &gainChange, encoder->fs_idx + , encoder->hrmode, encoder->frame_dms + ); + gain = round_fx(gain32); +#else + processAdjustGlobalGain_fx(&quantizedGain, quantizedGainMin, h_EncSetup->quantizedGainOff, &gain, &gain_e, + h_EncSetup->targetBitsQuant, h_EncSetup->mem_specBits, &gainChange, encoder->fs_idx); +#endif /* ENABLE_HR_MODE */ +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Quant. 2"); +#endif + IF (sub(gainChange, 1) == 0) + { +#ifdef ENABLE_HR_MODE + processQuantizeSpec_fx(d_fx, d_fx_exp, gain32, gain_e, q_d_fx24, encoder->yLen, h_EncSetup->targetBitsQuant, + h_EncSetup->targetBitsAri, NULL, &nBits, encoder->fs_idx, &lastnz, codingdata, &lsbMode, + 0, encoder->hrmode); +#else + processQuantizeSpec_fx(d_fx, d_fx_exp, gain, gain_e, q_d_fx16, encoder->yLen, h_EncSetup->targetBitsQuant, + h_EncSetup->targetBitsAri, NULL, &nBits, encoder->fs_idx, &lastnz, codingdata, &lsbMode, + 0); +#endif /* ENABLE_HR_MODE */ + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Res. Cod."); +#endif + IF (lsbMode == 0) + { + processResidualCoding_fx(d_fx_exp, d_fx, +#ifdef ENABLE_HR_MODE + q_d_fx24, +#else + q_d_fx16, +#endif +#ifdef ENABLE_HR_MODE + gain32, +#else + gain, +#endif + gain_e, encoder->yLen, h_EncSetup->targetBitsQuant, nBits, resBits, &numResBits +#ifdef ENABLE_HR_MODE + , encoder->hrmode +#endif + ); + } + ELSE + { + numResBits = 0; + move16(); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Noise fac"); +#endif + /* currentScratch Size = 2 * MAX_LEN bytes */ + IF (h_EncSetup->lfe == 0) + { + processNoiseFactor_fx(&fac_ns_idx, d_fx_exp, d_fx, +#ifdef ENABLE_HR_MODE + q_d_fx24, +#else + q_d_fx16, +#endif + gain, gain_e, BW_cutoff_idx, encoder->frame_dms, h_EncSetup->targetBytes, currentScratch +#ifdef ENABLE_HR_MODE + , encoder->hrmode +#endif + ); + } + ELSE + { + fac_ns_idx = 7; + move16(); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Entropy cod"); +#endif + processEncoderEntropy(bytes, &bp_side, &mask_side, h_EncSetup->targetBitsAri, h_EncSetup->targetBytes, + encoder->yLen, encoder->BW_cutoff_bits, tns_numfilters, lsbMode, lastnz, tns_order, + fac_ns_idx, quantizedGain, BW_cutoff_idx, ltpf_idx, L_scf_idx, bfi_ext, encoder->fs_idx); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Ari cod"); +#endif + processAriEncoder_fx(bytes, bp_side, mask_side, h_EncSetup->targetBitsAri, +#ifdef ENABLE_HR_MODE + q_d_fx24, +#else + q_d_fx16, +#endif + tns_order, tns_numfilters, indexes, lastnz, codingdata, resBits, numResBits, lsbMode, + h_EncSetup->enable_lpc_weighting, currentScratch); +#ifdef WMOPS + BASOP_sub_end(); +#endif + +#ifdef WMOPS + BASOP_sub_start("Reorder Bitstream Enc"); +#endif + test(); + IF (encoder->combined_channel_coding == 0 && h_EncSetup->n_pc > 0) + { +#ifdef WMOPS + BASOP_sub_start("Reorder Ari dec"); +#endif + +#ifdef ENABLE_HR_MODE + Word32 *xbuf = (Word32 *) scratchAlign(scratchBuffer, 0); + + processAriDecoder_fx(bytes, &bp_side, &mask_side, h_EncSetup->total_bits, encoder->yLen, encoder->fs_idx, + h_EncSetup->enable_lpc_weighting, tns_numfilters, lsbMode, lastnz, &gain, tns_order, + fac_ns_idx, quantizedGain, encoder->frame_dms, h_EncSetup->n_pc, 0, + shr_pos(h_EncSetup->total_bits, 3), 1, &gain, &b_left, &gain, + xbuf, + &gain, resBits, indexes, &gain, + currentScratch + , encoder->hrmode + ); +#else + + processAriDecoder_fx(bytes, &bp_side, &mask_side, h_EncSetup->total_bits, encoder->yLen, encoder->fs_idx, + h_EncSetup->enable_lpc_weighting, tns_numfilters, lsbMode, lastnz, &gain, tns_order, + fac_ns_idx, quantizedGain, encoder->frame_dms, h_EncSetup->n_pc, 0, + shr_pos(h_EncSetup->total_bits, 3), 1, &gain, &b_left, &gain, + codingdata, + &gain, resBits, indexes, &gain, + currentScratch + ); +#endif + +#ifdef WMOPS + BASOP_sub_end(); /* Ari dec */ +#endif + processReorderBitstream_fx(bytes, h_EncSetup->n_pccw, h_EncSetup->n_pc, b_left, currentScratch); + } +#ifdef WMOPS + BASOP_sub_end(); +#endif + + /* end q_d_fx16 */ +#ifdef WMOPS + BASOP_sub_end(); +#endif + + Dyn_Mem_Deluxe_Out(); +} + +int Enc_LC3PLUS(LC3PLUS_Enc *encoder, void **input, int bits_per_sample, UWord8 *output, void *scratch, Word16 bfi_ext) +{ + int ch = 0, output_size = 0; + int input_size = 0; + int totalBytes = (Word32)encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in); + int output_size2; + + UWord8 *lc3buf = output; + + for (ch = 0; ch < encoder->channels; ch++) + { + Enc_LC3PLUS_Channel(encoder, ch, bits_per_sample, input[ch], lc3buf, scratch, bfi_ext); + if (encoder->epmode && encoder->combined_channel_coding == 0) + { + output_size2 = totalBytes / encoder->channels + (ch < (totalBytes % encoder->channels)); +#ifdef WMOPS + BASOP_sub_start("fec_enc"); +#endif + + fec_encoder(encoder->epmode, encoder->epmr, lc3buf, encoder->channel_setup[ch]->targetBytes, output_size2, + encoder->channel_setup[ch]->n_pccw, scratch); + +#ifdef WMOPS + BASOP_sub_end(); +#endif + + lc3buf += output_size2; + output_size += output_size2; + } + else + { + lc3buf += encoder->channel_setup[ch]->targetBytes; + output_size += encoder->channel_setup[ch]->targetBytes; + } + } + + if (encoder->epmode > 0 && encoder->combined_channel_coding) + { + input_size = output_size; + output_size = (Word32)encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in); +#ifdef WMOPS + BASOP_sub_start("fec_enc"); +#endif + + fec_encoder(encoder->epmode, encoder->epmr, output, input_size, output_size, encoder->channel_setup[0]->n_pccw, + scratch); + +#ifdef WMOPS + BASOP_sub_end(); +#endif + } + + return output_size; +} + diff --git a/lib_lc3plus/estimate_global_gain_fx.c b/lib_lc3plus/estimate_global_gain_fx.c new file mode 100644 index 000000000..c6d1766b4 --- /dev/null +++ b/lib_lc3plus/estimate_global_gain_fx.c @@ -0,0 +1,506 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 nbitsSQ, +#ifdef ENABLE_HR_MODE + Word32 *gain, +#else + Word16 *gain, +#endif + Word16 *gain_e, + Word16 *quantizedGain, Word16 *quantizedGainMin, Word16 quantizedGainOff, + Word32 *targetBitsOff, Word16 *old_targetBits, Word16 old_specBits, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode, Word16 regBits, Word16 frame_dms +#endif +) +{ + + Word16 lg_4, tmp16, iszero, s; + Word32 ener, tmp32, x_max; + Word32 target, fac, offset; + Word32 *en; + Counter iter, i; + Word32 diff, diff2; +#ifdef ENABLE_HR_MODE + Word16 *en_exp = NULL; + Word32 M0, M1; +#endif + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processEstimateGlobalGain_fx", sizeof(struct { + Word16 lg_4, s, tmp16, iszero; + Word32 ener, tmp32, x_max; + Word32 target, fac, offset; + Word32 *en; + Counter i, iter; + Word32 diff, diff2; + })); +#endif + + en = (Word32 *)scratchAlign(scratchBuffer, + 0); /* Size = MAX_LEN bytes */ + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + M0 = 1; + M1 = 1; /* Regularization factor; needs´to be 1e-5, but 1e-5 is 0 in Q15 */ + en_exp = (Word16 *) scratchAlign(en, sizeof(*en) * MAX_LEN); + } +#endif + IF (*old_targetBits < 0) + { + *targetBitsOff = 0; + move16(); + } + ELSE + { + tmp32 = L_add(*targetBitsOff, L_deposit_h(sub(*old_targetBits, old_specBits))); + tmp32 = L_min((40 << 16), L_max(-(40 << 16), tmp32)); + *targetBitsOff = L_add(Mpy_32_16_lc3plus(*targetBitsOff, 26214), Mpy_32_16_lc3plus(tmp32, 6554)); + move16(); + } + + *old_targetBits = nbitsSQ; + move16(); + nbitsSQ = add(nbitsSQ, round_fx(*targetBitsOff)); + + lg_4 = shr_pos(lg, 2); + x_max = 0; + move32(); + +/* energy of quadruples with 9dB offset */ +#ifdef ENABLE_HR_MODE + IF (hrmode) + { + FOR (i = 0; i < lg_4; i++) + { + Word32 absval; + Word16 idx; + /* normalization */ + s = 31; + move16(); + + /* M1 requires a 32x16 mult with Q0 i, resulting in Q15. Keeping both M0 and M1 in same Q */ + /* Use Q15 for M0 and M1 calculation */ + idx = shl(i, 2); + + tmp32 = L_abs(x[0]); + absval = L_shr(tmp32, 16); + M0 = L_add(M0, absval); /* M0 += fabs(x[idx])*/ + M1 = L_add(M1, L_mult(absval, idx)); /* M1 += i*fabs(x[idx])*/ + idx = add(idx, 1); + + absval = L_abs(x[1]); + tmp32 = L_max(tmp32, absval); + absval = L_shr(tmp32, 16); + M0 = L_add(M0, absval); /* M0 += fabs(x[idx])*/ + M1 = L_add(M1, L_mult(absval, idx)); /* M1 += idx*fabs(x[idx])*/ + idx = add(idx, 1); + + absval = L_abs(x[2]); + tmp32 = L_max(tmp32, absval); + absval = L_shr(tmp32, 16); + M0 = L_add(M0, absval); /* M0 += fabs(x[idx])*/ + M1 = L_add(M1, L_mult(absval, idx)); /* M1 += idx*fabs(x[idx])*/ + idx = add(idx, 1); + + absval = L_abs(x[3]); + tmp32 = L_max(tmp32, absval); + absval = L_shr(tmp32, 16); + M0 = L_add(M0, absval); /* M0 += fabs(x[idx])*/ + M1 = L_add(M1, L_mult(absval, idx)); /* M1 += idx*fabs(x[idx])*/ + + x_max = L_max(x_max, tmp32); + + if (tmp32 != 0) + s = norm_l(tmp32); + + s = sub(s, 2); /* 2 bits headroom */ + + /* calc quadruple energy */ + ener = L_deposit_l(1); + + tmp16 = round_fx(L_shl(x[0], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[1], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[2], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[3], s)); + ener = L_mac(ener, tmp16, tmp16); + + s = shl_pos(sub(x_e, s), 1); + if (ener == 1 && s < 0) + s = 0; + IF (regBits > 0) + { + en[i] = ener; + en_exp[i] = s; + move32(); + } + ELSE + { + /* log */ + tmp32 = L_add(BASOP_Util_Log2_lc3plus(ener), L_shl_pos(L_deposit_l(s), 25)); /* log2, 6Q25 */ + tmp32 = L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 7), + 0x4E666); /* -> (28/20)*(7+10*tmp32/log2(10)), 16Q15 */ + en[i] = tmp32; + move32(); + } + + x += 4; + } + } + ELSE +#endif + { + FOR (i = 0; i < lg_4; i++) + { + /* normalization */ + s = 31; + move16(); + + tmp32 = L_abs(x[0]); + tmp32 = L_max(tmp32, L_abs(x[1])); + tmp32 = L_max(tmp32, L_abs(x[2])); + tmp32 = L_max(tmp32, L_abs(x[3])); + x_max = L_max(x_max, tmp32); + + if (tmp32 != 0) + s = norm_l(tmp32); + + s = sub(s, 2); /* 2 bits headroom */ + + /* calc quadruple energy */ + ener = L_deposit_l(1); + + tmp16 = round_fx(L_shl(x[0], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[1], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[2], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = round_fx(L_shl(x[3], s)); + ener = L_mac(ener, tmp16, tmp16); + + s = shl_pos(sub(x_e, s), 1); + if (ener == 1 && s < 0) + s = 0; + + /* log */ + tmp32 = L_add_sat(BASOP_Util_Log2_lc3plus(ener), L_shl_sat(L_deposit_l(s), 25)); /* log2, 6Q25 */ + tmp32 = + L_add(L_shr_pos(Mpy_32_16_lc3plus(tmp32, 0x436E), 6), 0x9CCCD); /* -> (28/20)*(7+10*tmp32/log2(10)), 15Q16 */ + en[i] = tmp32; + move32(); + x += 4; + } + } + + IF (x_max == 0) + { + *quantizedGainMin = quantizedGainOff; + move16(); + *quantizedGain = 0; + move16(); + *old_targetBits = -1; + move16(); + } + ELSE + { + Word32 sub_val = 0xFCDD38F; + /*28 * log10(32767 - 0.375) * (1 - 1e-7) in Q21 */ + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + /* + Original float code : + rB_offset = 8 * (1 - MIN(M1/M0, 2*frame_ms)/(2*frame_ms) + */ + Word16 ratio; + Word16 ratio_exp = 0; + Word32 regterm = MAX_32; /* 1 in Q31 */ + Word32 rB_offset, reg_val; + Word32 ratio_prod; + Word16 n_reg_val; + + if (M0 <= 0x7fff) + { + Word16 inv_M0 = Inv16_lc3plus(M0, &ratio_exp); /* Inverse in Q(15 - ratio_exp) */ + ratio = L_shr(Mpy_32_16_lc3plus(M1, inv_M0), 15 - ratio_exp); /* Integer ratio */ + } + else + { + Word16 M0_h = L_shr(M0, 15); + Word32 M1_h = L_shr(M1, 15); + + Word16 inv_M0 = Inv16_lc3plus(M0_h, &ratio_exp); /* Inverse in Q(15 - ratio_exp) */ + ratio = extract_l(L_shr(Mpy_32_16_lc3plus(M1_h, inv_M0), 15 - ratio_exp)); /* Integer ratio */ + } + + /* + regterm = MIN (M1 / M0, 2 *frame_ms) / (2 * frame_ms) + regterm = MIN (M1 * (10 / 2) / M0, frame_dms) / frame_dms + regterm = MIN ( ratio * 5, frame_dms) / frame_dms + */ + + ratio_prod = L_mult(ratio, 5); + + if (ratio_prod < frame_dms) + { + Word16 mult_factor = 0; + + SWITCH (frame_dms) /* 1 / frame_dms in Q15 */ + { + case 25: mult_factor = 1311; break; + case 50: mult_factor = 655; break; +#ifdef CR8_G_ADD_75MS + case 75: mult_factor = 437; break; +#endif + case 100: mult_factor = 328; break; + } + + /* ratio_prod < frame_dms. Hence Word16 can be used */ + + regterm = L_shl(L_mult(extract_l(ratio_prod), mult_factor), 15); /* result in Q31 */ + } + + rB_offset = L_sub(MAX_32, regterm); + /* Calculation in Q28 to prevent overflow. Subtraction result in Q31, downshift by 3 results in Q28. + Multiplication by 8 is implemented as upshift by 3. + */ + + /* + FLOAT code : reg_val = x_max * LC3_POW(2,-regBits - rB_offset); + */ + Word16 reg_val_e = x_e; + + IF(rB_offset > 0) + { + Word32 reg_exp = L_negate(L_add(L_shl(regBits, 25), L_shr(rB_offset, 3))); + reg_val = Mpy_32_32_lc3plus(x_max, BASOP_Util_InvLog2_lc3plus(reg_exp)); /* Product is in Q31 */ + /* reg_val is in Q(31-x_e) */ + } + ELSE + { + reg_val = x_max; + reg_val_e = sub(x_e, regBits); + } + + sub_val = 0x183BA045; + move16(); + /*28 * log10(32768*256 - 2) in Q21 */ + + /* + Adding LC3_POW(2, -31) to reg_val.2^-31 * 2^(31-x_e) = 2^-x_e. + If x_e is positive, this is below precision requirements to be used. + */ + + if (reg_val_e < 0) + { + reg_val = L_add_sat(reg_val, L_shl_sat(1, negate(reg_val_e))); + } + n_reg_val = norm_l(reg_val); + + FOR (i = 0; i < lg_4; i++) + { + ener = en[i]; + move16(); + s = en_exp[i]; + move16(); + + Word16 shift_val = sub(reg_val_e, s); + + IF (sub(n_reg_val, shift_val) > 0) + { + IF(shift_val > -32) + { + ener = L_add(ener, L_shl(reg_val, shift_val)); /* Match q formats */ + } + } + ELSE + { + IF (sub(shift_val, 32) >= 0 ) + { + ener = reg_val; + } + ELSE + { + ener = L_add_sat(reg_val, L_shr(ener, shift_val)); + } + s = reg_val_e; + } + + tmp32 = L_add(BASOP_Util_Log2_lc3plus(ener), L_shl_pos(L_deposit_l(s), 25)); /* log2, 6Q25 */ + tmp32 = L_add(L_shr_pos(Mpy_32_32_lc3plus(tmp32, 0x436E439A), 7), 0x4E666); /* -> (28/20)*(7+10*tmp32/log2(10)), 15Q16 */ + en[i] = tmp32; + move32(); + } + } +#endif + x_max = BASOP_Util_Log2_lc3plus(x_max); + /* Minimum gain */ + x_max = L_add(x_max, L_shl_pos(L_deposit_l(x_e), 25)); /* log2(x_max) in 6Q25 */ + x_max = L_sub( + Mpy_32_32_lc3plus(x_max, 0x436E439A), + sub_val); /* 28*log10(x_max/(32768-0.375)) = log2(x_max)*(28/log2(10))-28*log10(32768-0.375) in 10Q21 */ + /* 28/log1(10) is in Q27 + Mpy_32_32_lc3plus : Q25(x_max) + Q27 + Q1(Mpy_32_32_ss) - Q32 = Q21 */ + *quantizedGainMin = extract_l(L_shr_pos(L_add(x_max, (1 << 21) + (1 << 11)), 21)); + move16(); + ASSERT(*quantizedGainMin <= 255 + quantizedGainOff); + *quantizedGainMin = s_max(quantizedGainOff, s_min(add(255, quantizedGainOff), *quantizedGainMin)); + + offset = L_deposit_h(add(255, quantizedGainOff)); /* -> 127 */ + +#ifdef ENABLE_HR_MODE + IF(hrmode) + { + offset = L_shr_pos(offset, 2); + /* SQ scale: 4 bits / 6 dB per quadruple */ + target = L_mult(0x3EB8, nbitsSQ); /* -> (28/20) * (1.4) * nbitsSQ */ + + fac = L_add(0x400000, 0); /* -> 256 */ + /* find offset (0 to 127) */ + FOR (iter = 0; iter < 8; iter++) + { + fac = L_shr_pos(fac, 1); + offset = L_sub(offset, fac); + + ener = L_deposit_l(0); + iszero = 1; + move16(); + + FOR (i = lg_4 - 1; i >= 0; i--) + { + tmp32 = L_sub(L_shr_pos(en[i], 1), offset); + diff = L_sub(tmp32, 0x27333); /* 0x4E666 -> (28/20)*(7) in Q15 */ + if (diff < 0) + { + if (iszero == 0) + { + ener = L_add(ener, 0xF1EC); /* 0x1E3D7 -> (28/20)*(2.7) in Q15 */ + } + } + else + { + ener = L_add(ener, tmp32); + iszero = 0; + move16(); + + diff2 = L_sub(tmp32, 0x118000); /* 0x230000 -> (28/20)*(50) */ + if (diff2 >= 0) + { + ener = L_add(ener, diff2); + } + } + } + + /* if ener is above target -> increase offset */ + test(); + if (L_sub(ener, target) > 0 && iszero == 0) + { + offset = L_add(offset, fac); + } + } + tmp16 = extract_h(L_shl(offset, 2)); + } + ELSE +#endif + { + /* SQ scale: 4 bits / 6 dB per quadruple */ + target = L_shl_pos(L_mult(0x7D71, nbitsSQ), 1); /* -> (28/20) * (1.4) * nbitsSQ */ + fac = L_add(0x1000000, 0); /* -> 256 */ + + /* find offset (0 to 127) */ + FOR (iter = 0; iter < 8; iter++) + { + fac = L_shr_pos(fac, 1); + offset = L_sub(offset, fac); + + ener = L_deposit_l(0); + iszero = 1; + move16(); + FOR (i = lg_4 - 1; i >= 0; i--) + { + tmp32 = L_sub(en[i], offset); + diff = L_sub(tmp32, 0x9CCCD); /* 0x9CCCD -> (28/20)*(7) in Q16 */ + if (diff < 0) + { + if (iszero == 0) + { + ener = L_add_sat(ener, 0x3C7AE); /* 0x3C7AE -> (28/20)*(2.7) in Q16 */ + } + } + else + { + ener = L_add_sat(ener, tmp32); + iszero = 0; + move16(); + + diff2 = L_sub(tmp32, 0x460000); /* 0x460000 -> (28/20)*(50) in Q16 */ + if (diff2 >= 0) + { + ener = L_add_sat(ener, diff2); + } + } + + } + + /* if ener is above target -> increase offset */ + test(); + if (L_sub(ener, target) > 0 && iszero == 0) + { + offset = L_add(offset, fac); + } + } + tmp16 = extract_h(offset); + + } + + if (sub(tmp16, *quantizedGainMin) < 0) + { + *old_targetBits = -1; + move16(); + } + *quantizedGain = sub(s_max(*quantizedGainMin, tmp16), quantizedGainOff); + move16(); + } + +#ifdef ENABLE_HR_MODE + tmp32 = + Mpy_32_16_lc3plus(0x797CD707, L_shl_pos(add(*quantizedGain, quantizedGainOff), 6)); +#else + tmp32 = + L_shl_pos(L_mult0(add(*quantizedGain, quantizedGainOff), 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ +#endif + *gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); /* get exponent */ +#ifdef ENABLE_HR_MODE + *gain = BASOP_Util_InvLog2_lc3plus(L_or(tmp32, (Word32)0xFE000000)); +#else + *gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32,(Word32) 0xFE000000))); +#endif + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/fft_lc3plus.c b/lib_lc3plus/fft_lc3plus.c new file mode 100644 index 000000000..a86286d04 --- /dev/null +++ b/lib_lc3plus/fft_lc3plus.c @@ -0,0 +1,4537 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include "rom_basop_util.h" + +#ifdef ENABLE_FFT_RESCALE +#ifndef FFT_RESCALE_HR +#define FFT_RESCALE_HR 3 +#endif +#endif + +#define SCALEFACTORN2 3 +#define SCALEFACTOR4 3 +#define SCALEFACTOR5 4 +#define SCALEFACTOR8 4 +#define SCALEFACTOR15 5 +#define SCALEFACTOR30_1 5 +#define SCALEFACTOR30_2 1 +#define SCALEFACTOR32_1 5 +#define SCALEFACTOR32_2 1 + +#ifdef ENABLE_HR_MODE +#define Mpy_32_xx Mpy_32_32_lc3plus +#else +#define Mpy_32_xx Mpy_32_16_lc3plus +#endif + +#ifdef CR8_G_ADD_75MS +#define SCALEFACTOR6 4 +#define C61_32 (0x6ed9eba1) +#endif + +#define SCALEFACTOR10 5 +#define SCALEFACTOR16 5 +#define SCALEFACTOR20 5 +#define SCALEFACTOR30 6 +#define SCALEFACTOR32 6 +#define SCALEFACTOR40 7 +#define SCALEFACTOR48 8 +#define SCALEFACTOR60 7 +#define SCALEFACTOR64 7 +#define SCALEFACTOR80 8 +#define SCALEFACTOR90 9 +#define SCALEFACTOR96 9 +#define SCALEFACTOR120 8 +#define SCALEFACTOR128 8 +#define SCALEFACTOR160 8 +#define SCALEFACTOR180 10 +#define SCALEFACTOR192 10 +#define SCALEFACTOR240 9 +#define SCALEFACTOR256 9 +#define SCALEFACTOR384 11 + +#ifdef ENABLE_HR_MODE +#ifdef CR8_G_ADD_75MS +#define SCALEFACTOR360 11 +#endif +#ifndef ENABLE_FFT_30X16 +#define SCALEFACTOR480 10 +#else +#define SCALEFACTOR480 11 +#endif +#endif + +#ifdef ENABLE_HR_MODE +#undef L_shr_pos +#define L_shr_pos(x, y) (L_shr(L_add(L_shr((x), ((y)-1)),1),1)) +#endif + +#ifdef ENABLE_HR_MODE +#define FFTC(x) ((Word32)x) +#else +#define FFTC(x) WORD322WORD16((Word32)x) +#endif + +#define C31 (FFTC(0x91261468)) /* FL2WORD32( -0.86602540) -sqrt(3)/2 */ + +#define C51 (FFTC(0x79bc3854)) /* FL2WORD32( 0.95105652) */ +#define C52 (FFTC(0x9d839db0)) /* FL2WORD32(-1.53884180/2) */ +#define C53 (FFTC(0xd18053ce)) /* FL2WORD32(-0.36327126) */ +#define C54 (FFTC(0x478dde64)) /* FL2WORD32( 0.55901699) */ +#define C55 (FFTC(0xb0000001)) /* FL2WORD32(-1.25/2) */ + +#define C81 (FFTC(0x5a82799a)) /* FL2WORD32( 7.071067811865475e-1) */ +#define C82 (FFTC(0xa57d8666)) /* FL2WORD32(-7.071067811865475e-1) */ + +#define C161 (FFTC(0x5a82799a)) /* FL2WORD32( 7.071067811865475e-1) INV_SQRT2 */ +#define C162 (FFTC(0xa57d8666)) /* FL2WORD32(-7.071067811865475e-1) -INV_SQRT2 */ + +#define C163 (FFTC(0x7641af3d)) /* FL2WORD32( 9.238795325112867e-1) COS_PI_DIV8 */ +#define C164 (FFTC(0x89be50c3)) /* FL2WORD32(-9.238795325112867e-1) -COS_PI_DIV8 */ + +#define C165 (FFTC(0x30fbc54d)) /* FL2WORD32( 3.826834323650898e-1) COS_3PI_DIV8 */ +#define C166 (FFTC(0xcf043ab3)) /* FL2WORD32(-3.826834323650898e-1) -COS_3PI_DIV8 */ + +#define C51_32 (0x79bc3854) /* FL2WORD32( 0.95105652) */ +#define C52_32 (0x9d839db0) /* FL2WORD32(-1.53884180/2) */ +#define C53_32 (0xd18053ce) /* FL2WORD32(-0.36327126) */ +#define C54_32 (0x478dde64) /* FL2WORD32( 0.55901699) */ +#define C55_32 (0xb0000001) /* FL2WORD32(-1.25/2) */ + + +#define C81_32 (0x5a82799a) /* FL2WORD32( 7.071067811865475e-1) */ +#define C82_32 (0xa57d8666) /* FL2WORD32(-7.071067811865475e-1) */ + +#if defined(ENABLE_HR_MODE) + +# define cplxMpy4_16_0(re, im, a, b, c, d) \ + do \ + { \ + re = L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)); \ + move32(); \ + im = L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)); \ + move32(); \ + } while (0) + +# define cplxMpy4_16_1(re, im, a, b) \ + do \ + { \ + re = a; \ + move32(); \ + im = b; \ + move32(); \ + } while (0) + +# endif + +#define Mpy3_0(s12, s13, s14, s15, t0, t1, t2, t3) \ + do \ + { \ + s12 = Mpy_32_32_lc3plus(L_add(t0, t2), C81_32); \ + s14 = Mpy_32_32_lc3plus(L_sub(t0, t2), C81_32); \ + s13 = Mpy_32_32_lc3plus(L_sub(t3, t1), C81_32); \ + s15 = Mpy_32_32_lc3plus(L_add(t1, t3), C82_32); \ + } while (0) + +#define cplxMpy3_0(a, b, c, d) \ + do \ + { \ + as = L_shr_pos(a, 1); \ + bs = L_shr_pos(b, 1); \ + a = L_sub(Mpy_32_32_lc3plus(as, c), Mpy_32_32_lc3plus(bs, d)); \ + b = L_add(Mpy_32_32_lc3plus(as, d), Mpy_32_32_lc3plus(bs, c)); \ + } while (0) + +#ifdef ENABLE_HR_MODE +#define cplxMpy4_4_0(re, im, a, b, c, d) \ + re = L_shr_pos(L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)), SCALEFACTOR60 - SCALEFACTOR15); \ + im = L_shr_pos(L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)), SCALEFACTOR60 - SCALEFACTOR15); + +# define cplxMpy4_4_1(re, im, a, b) \ + re = L_shr_pos(a, SCALEFACTOR60 - SCALEFACTOR15); \ + im = L_shr_pos(b, SCALEFACTOR60 - SCALEFACTOR15); +#else +#define cplxMpy4_4_0(re, im, a, b, c, d) \ + re = L_shr(L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)), SCALEFACTOR60 - SCALEFACTOR15); \ + im = L_shr(L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)), SCALEFACTOR60 - SCALEFACTOR15); + +#define cplxMpy4_4_1(re, im, a, b) \ + re = L_shr(a, SCALEFACTOR60 - SCALEFACTOR15); \ + im = L_shr(b, SCALEFACTOR60 - SCALEFACTOR15); +#endif + +#define cplxMpy4_8_0(re, im, a, b, c, d) \ + do \ + { \ + re = L_shr_pos(L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)), 1); \ + im = L_shr_pos(L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)), 1); \ + } while (0) + + +#define cplxMpy4_8_1(re, im, a, b) \ + do \ + { \ + re = L_shr_pos(a, 1); \ + im = L_shr_pos(b, 1); \ + } while (0) + + +#define cplxMpy4_8_2(re, im, a, b, c, d) \ + do \ + { \ + re = L_shr_pos(L_add(Mpy_32_32_lc3plus(a, c), Mpy_32_32_lc3plus(b, d)), 1); \ + im = L_shr_pos(L_sub(Mpy_32_32_lc3plus(b, c), Mpy_32_32_lc3plus(a, d)), 1); \ + } while (0) + + +#define cplxMpy4_12_0(re, im, a, b, c, d) \ + do \ + { \ + re = L_sub(Mpy_32_xx(a, c), Mpy_32_xx(b, d)); \ + move32(); \ + im = L_add(Mpy_32_xx(a, d), Mpy_32_xx(b, c)); \ + move32(); \ + } while (0) + +#define cplxMpy4_12_1(re, im, a, b) \ + do \ + { \ + re = a; \ + move32(); \ + im = b; \ + move32(); \ + } while (0) + + +static void fft4(Word32 *x) +{ + Dyn_Mem_Deluxe_In(Word32 x0, x1, x2, x3, x4, x5, x6, x7; Word32 t0, t1, t2, t3, t4, t5, t6, t7;); + + x0 = L_shr_pos(x[0], SCALEFACTOR4); + x1 = L_shr_pos(x[1], SCALEFACTOR4); + x2 = L_shr_pos(x[2], SCALEFACTOR4); + x3 = L_shr_pos(x[3], SCALEFACTOR4); + x4 = L_shr_pos(x[4], SCALEFACTOR4); + x5 = L_shr_pos(x[5], SCALEFACTOR4); + x6 = L_shr_pos(x[6], SCALEFACTOR4); + x7 = L_shr_pos(x[7], SCALEFACTOR4); + + /* Pre-additions */ + t0 = L_add(x0, x4); + t2 = L_sub(x0, x4); + t1 = L_add(x1, x5); + t3 = L_sub(x1, x5); + t4 = L_add(x2, x6); + t7 = L_sub(x2, x6); + t5 = L_add(x7, x3); + t6 = L_sub(x7, x3); + + /* Post-additions */ + x[0] = L_add(t0, t4); + x[1] = L_add(t1, t5); + x[2] = L_sub(t2, t6); + x[3] = L_sub(t3, t7); + x[4] = L_sub(t0, t4); + x[5] = L_sub(t1, t5); + x[6] = L_add(t2, t6); + x[7] = L_add(t3, t7); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 5-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR5 bits. + * + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + + +static void fft5(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 x0, x1, x2, x3, x4; Word32 r1, r2, r3, r4; Word32 s1, s2, s3, s4; Word32 t;); + + /* real part */ + x0 = L_shr_pos(re[s * 0], SCALEFACTOR5); + x1 = L_shr_pos(re[s * 1], SCALEFACTOR5); + x2 = L_shr_pos(re[s * 2], SCALEFACTOR5); + x3 = L_shr_pos(re[s * 3], SCALEFACTOR5); + x4 = L_shr_pos(re[s * 4], SCALEFACTOR5); + + r1 = L_add(x1, x4); + r4 = L_sub(x1, x4); + r3 = L_add(x2, x3); + r2 = L_sub(x2, x3); + t = Mpy_32_32_lc3plus(L_sub(r1, r3), C54_32); + r1 = L_add(r1, r3); + re[0] = L_add(x0, r1); + move32(); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + r1 = L_add(re[0], (L_shl_pos(Mpy_32_32_lc3plus(r1, C55_32), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_32_lc3plus(L_add(r4, r2), C51_32); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + r4 = L_add(t, L_shl_pos(Mpy_32_32_lc3plus(r4, C52_32), 1)); + r2 = L_add(t, Mpy_32_32_lc3plus(r2, C53_32)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 0], SCALEFACTOR5); + x1 = L_shr_pos(im[s * 1], SCALEFACTOR5); + x2 = L_shr_pos(im[s * 2], SCALEFACTOR5); + x3 = L_shr_pos(im[s * 3], SCALEFACTOR5); + x4 = L_shr_pos(im[s * 4], SCALEFACTOR5); + + s1 = L_add(x1, x4); + s4 = L_sub(x1, x4); + s3 = L_add(x2, x3); + s2 = L_sub(x2, x3); + t = Mpy_32_32_lc3plus(L_sub(s1, s3), C54_32); + s1 = L_add(s1, s3); + im[0] = L_add(x0, s1); + move32(); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + s1 = L_add(im[0], L_shl_pos(Mpy_32_32_lc3plus(s1, C55_32), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_32_lc3plus(L_add(s4, s2), C51_32); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + s4 = L_add(t, L_shl_pos(Mpy_32_32_lc3plus(s4, C52_32), 1)); + s2 = L_add(t, Mpy_32_32_lc3plus(s2, C53_32)); + + /* combination */ + re[s * 1] = L_add(r1, s2); + move32(); + re[s * 4] = L_sub(r1, s2); + move32(); + re[s * 2] = L_sub(r3, s4); + move32(); + re[s * 3] = L_add(r3, s4); + move32(); + + im[s * 1] = L_sub(s1, r2); + move32(); + im[s * 4] = L_add(s1, r2); + move32(); + im[s * 2] = L_add(s3, r4); + move32(); + im[s * 3] = L_sub(s3, r4); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 6-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR6 bits. + * + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] st stride real and imag input / output + * + * \return void + */ + +#ifdef CR8_G_ADD_75MS +static void fft6(Word32 *re, Word32 *im, Word16 st) +{ + Dyn_Mem_Deluxe_In(Word32 x0, x1, x2, x3, x4, x5; Word32 r1o, r2o, i1e, i2e, i1o, i2o; Word32 t, s;); + + /* process real parts */ + + x0 = L_shr_pos(re[0 * st], SCALEFACTOR6); + x1 = L_shr_pos(re[1 * st], SCALEFACTOR6); + x2 = L_shr_pos(re[2 * st], SCALEFACTOR6); + x3 = L_shr_pos(re[3 * st], SCALEFACTOR6); + x4 = L_shr_pos(re[4 * st], SCALEFACTOR6); + x5 = L_shr_pos(re[5 * st], SCALEFACTOR6); + + t = L_add(x0, L_add(x2, x4)); + s = L_add(x1, L_add(x3, x5)); + re[0 * st] = L_add(t, s); + move32(); + re[3 * st] = L_sub(t, s); + move32(); + t = L_sub(x0, L_shr_pos(L_add(x2, x4), 1)); + + re[1 * st] = t; + move32(); + re[2 * st] = t; + move32(); + re[4 * st] = t; + move32(); + re[5 * st] = t; + move32(); + + s = Mpy_32_32_lc3plus(L_sub(x4, x2), C61_32); + + i1e = s; + i2e = -s; + + t = L_sub(x1, L_shr_pos(L_add(x3, x5), 1)); + s = Mpy_32_32_lc3plus(L_sub(x5, x3), C61_32); + + r1o = r2o = t; + i1o = s; + i2o = -s; + + x0 = L_shr_pos(im[0 * st], SCALEFACTOR6); + x1 = L_shr_pos(im[1 * st], SCALEFACTOR6); + x2 = L_shr_pos(im[2 * st], SCALEFACTOR6); + x3 = L_shr_pos(im[3 * st], SCALEFACTOR6); + x4 = L_shr_pos(im[4 * st], SCALEFACTOR6); + x5 = L_shr_pos(im[5 * st], SCALEFACTOR6); + + t = L_add(x0, L_add(x2, x4)); + s = L_add(x1, L_add(x3, x5)); + + im[0 * st] = L_add(t, s); + move32(); + im[3 * st] = L_sub(t, s); + move32(); + + t = Mpy_32_32_lc3plus(L_sub(x2, x4), C61_32); + s = L_sub(x0, L_shr_pos(L_add(x2, x4), 1)); + + re[1 * st] = L_add(re[1 * st], t); + move32(); + re[2 * st] = L_sub(re[2 * st], t); + move32(); + re[4 * st] = L_add(re[4 * st], t); + move32(); + re[5 * st] = L_sub(re[5 * st], t); + move32(); + + i1e = L_add(i1e, s); + i2e = L_add(i2e, s); + + t = Mpy_32_32_lc3plus(L_sub(x3, x5), C61_32); + s = L_sub(x1, L_shr_pos(L_add(x5, x3), 1)); + + r1o = L_add(r1o, t); + r2o = L_sub(r2o, t); + + i1o = L_add(i1o, s); + i2o = L_add(i2o, s); + + t = L_add(L_shr_pos(r1o, 1), Mpy_32_32_lc3plus(i1o, C61_32)); + s = L_sub(L_shr_pos(i1o, 1), Mpy_32_32_lc3plus(r1o, C61_32)); + + re[1 * st] = L_add(re[1 * st], t); + move32(); + im[1 * st] = L_add(i1e, s); + move32(); + + re[4 * st] = L_sub(re[4 * st], t); + move32(); + im[4 * st] = L_sub(i1e, s); + move32(); + + t = L_sub(Mpy_32_32_lc3plus(i2o, C61_32), L_shr_pos(r2o, 1)); + s = L_negate(L_add(Mpy_32_32_lc3plus(r2o, C61_32), L_shr_pos(i2o, 1))); + + re[2 * st] = L_add(re[2 * st], t); + move32(); + im[2 * st] = L_add(i2e, s); + move32(); + + re[5 * st] = L_sub(re[5 * st], t); + move32(); + im[5 * st] = L_sub(i2e, s); + move32(); + + Dyn_Mem_Deluxe_Out(); +} +#endif + +/** + * \brief Function performs a complex 8-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR8 bits. + * + * WOPS with 32x16 bit multiplications: 108 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + +static void fft8(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 x00, x01, x02, x03, x04, x05, x06, x07; Word32 x08, x09, x10, x11, x12, x13, x14, x15; + Word32 t00, t01, t02, t03, t04, t05, t06, t07; Word32 t08, t09, t10, t11, t12, t13, t14, t15; + Word32 s00, s01, s02, s03, s04, s05, s06, s07; Word32 s08, s09, s10, s11, s12, s13, s14, s15;); + + /* Pre-additions */ + + x00 = L_shr_pos(re[s * 0], SCALEFACTOR8); + x01 = L_shr_pos(im[s * 0], SCALEFACTOR8); + x02 = L_shr_pos(re[s * 1], SCALEFACTOR8); + x03 = L_shr_pos(im[s * 1], SCALEFACTOR8); + x04 = L_shr_pos(re[s * 2], SCALEFACTOR8); + x05 = L_shr_pos(im[s * 2], SCALEFACTOR8); + x06 = L_shr_pos(re[s * 3], SCALEFACTOR8); + x07 = L_shr_pos(im[s * 3], SCALEFACTOR8); + x08 = L_shr_pos(re[s * 4], SCALEFACTOR8); + x09 = L_shr_pos(im[s * 4], SCALEFACTOR8); + x10 = L_shr_pos(re[s * 5], SCALEFACTOR8); + x11 = L_shr_pos(im[s * 5], SCALEFACTOR8); + x12 = L_shr_pos(re[s * 6], SCALEFACTOR8); + x13 = L_shr_pos(im[s * 6], SCALEFACTOR8); + x14 = L_shr_pos(re[s * 7], SCALEFACTOR8); + x15 = L_shr_pos(im[s * 7], SCALEFACTOR8); + + t00 = L_add(x00, x08); + t02 = L_sub(x00, x08); + t01 = L_add(x01, x09); + t03 = L_sub(x01, x09); + t04 = L_add(x02, x10); + t06 = L_sub(x02, x10); + t05 = L_add(x03, x11); + t07 = L_sub(x03, x11); + t08 = L_add(x04, x12); + t10 = L_sub(x04, x12); + t09 = L_add(x05, x13); + t11 = L_sub(x05, x13); + t12 = L_add(x06, x14); + t14 = L_sub(x06, x14); + t13 = L_add(x07, x15); + t15 = L_sub(x07, x15); + + /* Pre-additions and core multiplications */ + + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + + t01 = L_add(t06, t14); + t02 = L_sub(t06, t14); + t00 = L_add(t07, t15); + t03 = L_sub(t07, t15); + + s12 = Mpy_32_xx(L_add(t00, t02), C81); + s14 = Mpy_32_xx(L_sub(t00, t02), C81); + s13 = Mpy_32_xx(L_sub(t03, t01), C81); + s15 = Mpy_32_xx(L_add(t01, t03), C82); + + /* Post-additions */ + + re[s * 0] = L_add(s00, s02); + move32(); + re[s * 4] = L_sub(s00, s02); + move32(); + im[s * 0] = L_add(s01, s03); + move32(); + im[s * 4] = L_sub(s01, s03); + move32(); + re[s * 2] = L_sub(s04, s06); + move32(); + re[s * 6] = L_add(s04, s06); + move32(); + im[s * 2] = L_sub(s05, s07); + move32(); + im[s * 6] = L_add(s05, s07); + move32(); + re[s * 3] = L_add(s08, s14); + move32(); + re[s * 7] = L_sub(s08, s14); + move32(); + im[s * 3] = L_add(s09, s15); + move32(); + im[s * 7] = L_sub(s09, s15); + move32(); + re[s * 1] = L_add(s10, s12); + move32(); + re[s * 5] = L_sub(s10, s12); + move32(); + im[s * 1] = L_add(s11, s13); + move32(); + im[s * 5] = L_sub(s11, s13); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 10-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR10 bits. + * + * WOPS with 32x16 bit multiplications: 196 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + + +static void fft10(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 t; Word32 x0, x1, x2, x3, x4; Word32 r1, r2, r3, r4; Word32 s1, s2, s3, s4; + Word32 y00, y01, y02, y03, y04, y05, y06, y07, y08, y09; + Word32 y10, y11, y12, y13, y14, y15, y16, y17, y18, y19;); + + /* 2 fft5 stages */ + + /* real part */ + x0 = L_shr_pos(re[s * 0], SCALEFACTOR10); + x1 = L_shr_pos(re[s * 2], SCALEFACTOR10); + x2 = L_shr_pos(re[s * 4], SCALEFACTOR10); + x3 = L_shr_pos(re[s * 6], SCALEFACTOR10); + x4 = L_shr_pos(re[s * 8], SCALEFACTOR10); + + r1 = L_add(x3, x2); + r4 = L_sub(x3, x2); + r3 = L_add(x1, x4); + r2 = L_sub(x1, x4); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y00 = L_add(x0, r1); + r1 = L_add(y00, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 0], SCALEFACTOR10); + x1 = L_shr_pos(im[s * 2], SCALEFACTOR10); + x2 = L_shr_pos(im[s * 4], SCALEFACTOR10); + x3 = L_shr_pos(im[s * 6], SCALEFACTOR10); + x4 = L_shr_pos(im[s * 8], SCALEFACTOR10); + + s1 = L_add(x3, x2); + s4 = L_sub(x3, x2); + s3 = L_add(x1, x4); + s2 = L_sub(x1, x4); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y01 = L_add(x0, s1); + s1 = L_add(y01, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y04 = L_add(r1, s2); + y16 = L_sub(r1, s2); + y08 = L_sub(r3, s4); + y12 = L_add(r3, s4); + + y05 = L_sub(s1, r2); + y17 = L_add(s1, r2); + y09 = L_add(s3, r4); + y13 = L_sub(s3, r4); + + /* real part */ + x0 = L_shr_pos(re[s * 5], SCALEFACTOR10); + x1 = L_shr_pos(re[s * 1], SCALEFACTOR10); + x2 = L_shr_pos(re[s * 3], SCALEFACTOR10); + x3 = L_shr_pos(re[s * 7], SCALEFACTOR10); + x4 = L_shr_pos(re[s * 9], SCALEFACTOR10); + + r1 = L_add(x1, x4); + r4 = L_sub(x1, x4); + r3 = L_add(x3, x2); + r2 = L_sub(x3, x2); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y02 = L_add(x0, r1); + r1 = L_add(y02, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 5], SCALEFACTOR10); + x1 = L_shr_pos(im[s * 1], SCALEFACTOR10); + x2 = L_shr_pos(im[s * 3], SCALEFACTOR10); + x3 = L_shr_pos(im[s * 7], SCALEFACTOR10); + x4 = L_shr_pos(im[s * 9], SCALEFACTOR10); + + s1 = L_add(x1, x4); + s4 = L_sub(x1, x4); + s3 = L_add(x3, x2); + s2 = L_sub(x3, x2); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y03 = L_add(x0, s1); + s1 = L_add(y03, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y06 = L_add(r1, s2); + y18 = L_sub(r1, s2); + y10 = L_sub(r3, s4); + y14 = L_add(r3, s4); + + y07 = L_sub(s1, r2); + y19 = L_add(s1, r2); + y11 = L_add(s3, r4); + y15 = L_sub(s3, r4); + + /* 5 fft2 stages */ + re[s * 0] = L_add(y00, y02); + move32(); + im[s * 0] = L_add(y01, y03); + move32(); + re[s * 5] = L_sub(y00, y02); + move32(); + im[s * 5] = L_sub(y01, y03); + move32(); + + re[s * 2] = L_add(y04, y06); + move32(); + im[s * 2] = L_add(y05, y07); + move32(); + re[s * 7] = L_sub(y04, y06); + move32(); + im[s * 7] = L_sub(y05, y07); + move32(); + + re[s * 4] = L_add(y08, y10); + move32(); + im[s * 4] = L_add(y09, y11); + move32(); + re[s * 9] = L_sub(y08, y10); + move32(); + im[s * 9] = L_sub(y09, y11); + move32(); + + re[s * 6] = L_add(y12, y14); + move32(); + im[s * 6] = L_add(y13, y15); + move32(); + re[s * 1] = L_sub(y12, y14); + move32(); + im[s * 1] = L_sub(y13, y15); + move32(); + + re[s * 8] = L_add(y16, y18); + move32(); + im[s * 8] = L_add(y17, y19); + move32(); + re[s * 3] = L_sub(y16, y18); + move32(); + im[s * 3] = L_sub(y17, y19); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 15-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR15 bits. + * + * WOPS with 32x16 bit multiplications: 354 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + +static void fft15(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 t; Word32 r1, r2, r3, r4; Word32 s1, s2, s3, s4; + Word32 x00, x01, x02, x03, x04, x05, x06, x07, x08, x09; + Word32 x10, x11, x12, x13, x14, x15, x16, x17, x18, x19; + Word32 x20, x21, x22, x23, x24, x25, x26, x27, x28, x29; + Word32 y00, y01, y02, y03, y04, y05, y06, y07, y08, y09; + Word32 y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + Word32 y20, y21, y22, y23, y24, y25, y26, y27, y28, y29;); + + x00 = L_shr_pos(re[s * 0], SCALEFACTOR15); + x01 = L_shr_pos(im[s * 0], SCALEFACTOR15); + x02 = L_shr_pos(re[s * 3], SCALEFACTOR15); + x03 = L_shr_pos(im[s * 3], SCALEFACTOR15); + x04 = L_shr_pos(re[s * 6], SCALEFACTOR15); + x05 = L_shr_pos(im[s * 6], SCALEFACTOR15); + x06 = L_shr_pos(re[s * 9], SCALEFACTOR15); + x07 = L_shr_pos(im[s * 9], SCALEFACTOR15); + x08 = L_shr_pos(re[s * 12], SCALEFACTOR15); + x09 = L_shr_pos(im[s * 12], SCALEFACTOR15); + + x10 = L_shr_pos(re[s * 5], SCALEFACTOR15); + x11 = L_shr_pos(im[s * 5], SCALEFACTOR15); + x12 = L_shr_pos(re[s * 8], SCALEFACTOR15); + x13 = L_shr_pos(im[s * 8], SCALEFACTOR15); + x14 = L_shr_pos(re[s * 11], SCALEFACTOR15); + x15 = L_shr_pos(im[s * 11], SCALEFACTOR15); + x16 = L_shr_pos(re[s * 14], SCALEFACTOR15); + x17 = L_shr_pos(im[s * 14], SCALEFACTOR15); + x18 = L_shr_pos(re[s * 2], SCALEFACTOR15); + x19 = L_shr_pos(im[s * 2], SCALEFACTOR15); + + x20 = L_shr_pos(re[s * 10], SCALEFACTOR15); + x21 = L_shr_pos(im[s * 10], SCALEFACTOR15); + x22 = L_shr_pos(re[s * 13], SCALEFACTOR15); + x23 = L_shr_pos(im[s * 13], SCALEFACTOR15); + x24 = L_shr_pos(re[s * 1], SCALEFACTOR15); + x25 = L_shr_pos(im[s * 1], SCALEFACTOR15); + x26 = L_shr_pos(re[s * 4], SCALEFACTOR15); + x27 = L_shr_pos(im[s * 4], SCALEFACTOR15); + x28 = L_shr_pos(re[s * 7], SCALEFACTOR15); + x29 = L_shr_pos(im[s * 7], SCALEFACTOR15); + + /* 1. FFT5 stage */ + + /* real part */ + r1 = L_add(x02, x08); + r4 = L_sub(x02, x08); + r3 = L_add(x04, x06); + r2 = L_sub(x04, x06); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y00 = L_add(x00, r1); + r1 = L_add(y00, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x03, x09); + s4 = L_sub(x03, x09); + s3 = L_add(x05, x07); + s2 = L_sub(x05, x07); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y01 = L_add(x01, s1); + s1 = L_add(y01, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y02 = L_add(r1, s2); + y08 = L_sub(r1, s2); + y04 = L_sub(r3, s4); + y06 = L_add(r3, s4); + + y03 = L_sub(s1, r2); + y09 = L_add(s1, r2); + y05 = L_add(s3, r4); + y07 = L_sub(s3, r4); + + /* 2. FFT5 stage */ + + /* real part */ + r1 = L_add(x12, x18); + r4 = L_sub(x12, x18); + r3 = L_add(x14, x16); + r2 = L_sub(x14, x16); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y10 = L_add(x10, r1); + r1 = L_add(y10, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x13, x19); + s4 = L_sub(x13, x19); + s3 = L_add(x15, x17); + s2 = L_sub(x15, x17); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y11 = L_add(x11, s1); + s1 = L_add(y11, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y12 = L_add(r1, s2); + y18 = L_sub(r1, s2); + y14 = L_sub(r3, s4); + y16 = L_add(r3, s4); + + y13 = L_sub(s1, r2); + y19 = L_add(s1, r2); + y15 = L_add(s3, r4); + y17 = L_sub(s3, r4); + + /* 3. FFT5 stage */ + + /* real part */ + r1 = L_add(x22, x28); + r4 = L_sub(x22, x28); + r3 = L_add(x24, x26); + r2 = L_sub(x24, x26); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y20 = L_add(x20, r1); + r1 = L_add(y20, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x23, x29); + s4 = L_sub(x23, x29); + s3 = L_add(x25, x27); + s2 = L_sub(x25, x27); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y21 = L_add(x21, s1); + s1 = L_add(y21, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y22 = L_add(r1, s2); + y28 = L_sub(r1, s2); + y24 = L_sub(r3, s4); + y26 = L_add(r3, s4); + + y23 = L_sub(s1, r2); + y29 = L_add(s1, r2); + y25 = L_add(s3, r4); + y27 = L_sub(s3, r4); + + /* 1. FFT3 stage */ + + /* real part */ + r1 = L_add(y10, y20); + r2 = Mpy_32_xx(L_sub(y10, y20), C31); + re[s * 0] = L_add(y00, r1); + move32(); + r1 = L_sub(y00, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y11, y21); + s2 = Mpy_32_xx(L_sub(y11, y21), C31); + im[s * 0] = L_add(y01, s1); + move32(); + s1 = L_sub(y01, L_shr_pos(s1, 1)); + + /* combination */ + re[s * 10] = L_sub(r1, s2); + move32(); + re[s * 5] = L_add(r1, s2); + move32(); + im[s * 10] = L_add(s1, r2); + move32(); + im[s * 5] = L_sub(s1, r2); + move32(); + + /* 2. FFT3 stage */ + + /* real part */ + r1 = L_add(y12, y22); + r2 = Mpy_32_xx(L_sub(y12, y22), C31); + re[s * 6] = L_add(y02, r1); + move32(); + r1 = L_sub(y02, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y13, y23); + s2 = Mpy_32_xx(L_sub(y13, y23), C31); + im[s * 6] = L_add(y03, s1); + move32(); + s1 = L_sub(y03, L_shr_pos(s1, 1)); + + /* combination */ + re[s * 1] = L_sub(r1, s2); + move32(); + re[s * 11] = L_add(r1, s2); + move32(); + im[s * 1] = L_add(s1, r2); + move32(); + im[s * 11] = L_sub(s1, r2); + move32(); + + /* 3. FFT3 stage */ + + /* real part */ + r1 = L_add(y14, y24); + r2 = Mpy_32_xx(L_sub(y14, y24), C31); + re[s * 12] = L_add(y04, r1); + move32(); + r1 = L_sub(y04, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y15, y25); + s2 = Mpy_32_xx(L_sub(y15, y25), C31); + im[s * 12] = L_add(y05, s1); + move32(); + s1 = L_sub(y05, L_shr_pos(s1, 1)); + + /* combination */ + re[s * 7] = L_sub(r1, s2); + move32(); + re[s * 2] = L_add(r1, s2); + move32(); + im[s * 7] = L_add(s1, r2); + move32(); + im[s * 2] = L_sub(s1, r2); + move32(); + + /* 4. FFT3 stage */ + + /* real part */ + r1 = L_add(y16, y26); + r2 = Mpy_32_xx(L_sub(y16, y26), C31); + re[s * 3] = L_add(y06, r1); + move32(); + r1 = L_sub(y06, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y17, y27); + s2 = Mpy_32_xx(L_sub(y17, y27), C31); + im[s * 3] = L_add(y07, s1); + move32(); + s1 = L_sub(y07, L_shr_pos(s1, 1)); + + /* combination */ + re[s * 13] = L_sub(r1, s2); + move32(); + re[s * 8] = L_add(r1, s2); + move32(); + im[s * 13] = L_add(s1, r2); + move32(); + im[s * 8] = L_sub(s1, r2); + move32(); + + /* 5. FFT3 stage */ + + /* real part */ + r1 = L_add(y18, y28); + r2 = Mpy_32_xx(L_sub(y18, y28), C31); + re[s * 9] = L_add(y08, r1); + move32(); + r1 = L_sub(y08, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y19, y29); + s2 = Mpy_32_xx(L_sub(y19, y29), C31); + im[s * 9] = L_add(y09, s1); + move32(); + s1 = L_sub(y09, L_shr_pos(s1, 1)); + + /* combination */ + re[s * 4] = L_sub(r1, s2); + move32(); + re[s * 14] = L_add(r1, s2); + move32(); + im[s * 4] = L_add(s1, r2); + move32(); + im[s * 14] = L_sub(s1, r2); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +#ifdef CR8_G_ADD_75MS + +#define STC(x) (x) +const Word32 RotVectorReal12[] = +{ + STC(0x6ed9eba1), STC(0x40000000), + STC(0x40000000), STC(0xc0000000), +#ifndef FFT12_UNROLLED_ENABLE + STC(0x00000000), STC(0x80000000), +#endif +}; + +const Word32 RotVectorImag12[] = +{ + STC(0x40000000), STC(0x6ed9eba1), + STC(0x6ed9eba1), STC(0x6ed9eba1), +#ifndef FFT12_UNROLLED_ENABLE + STC(0x7fffffff), STC(0x00000000), +#endif +}; + +static void fft12(Word32 *pInput) +{ + Dyn_Mem_Deluxe_In(Word32 aDst[24]; Word32 * pSrc, *pDst; Counter i; Word32 r1, r2, s1, s2, pD; Word32 re, im; + Word32 vre, vim;); + + pSrc = pInput; + move16(); + pDst = aDst; + move16(); + + /* First 3*2 samples are shifted right by 2 before output */ + r1 = L_add(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)); + r2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)), C31); + pD = L_shr_pos(pSrc[0], 2); + pDst[0] = L_shr_pos(L_add(pD, r1), 1); + r1 = L_sub(pD, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)); + s2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)), C31); + pD = L_shr_pos(pSrc[1], 2); + pDst[1] = L_shr_pos(L_add(pD, s1), 1); + s1 = L_sub(pD, L_shr_pos(s1, 1)); + + r1 = L_shr_pos(r1, 1); + r2 = L_shr_pos(r2, 1); + s1 = L_shr_pos(s1, 1); + s2 = L_shr_pos(s2, 1); + + /* combination */ + pDst[2] = L_sub(r1, s2); + pDst[3] = L_add(s1, r2); + pDst[4] = L_add(r1, s2); + pDst[5] = L_sub(s1, r2); + pSrc += 2; + pDst += 6; + + const Word32 *pVecRe = RotVectorReal12; + const Word32 *pVecIm = RotVectorImag12; + + + + FOR (i = 0; i < 2; i++) + { + /* sample 0,1 are shifted right by 2 before output */ + /* sample 2,3 4,5 are shifted right by 1 and complex multiplied before output */ + + r1 = L_add(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)); + r2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)), C31); + pD = L_shr_pos(pSrc[0], 2); + pDst[0] = L_shr_pos(L_add(pD, r1), 1); + r1 = L_sub(pD, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)); + s2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)), C31); + pD = L_shr_pos(pSrc[1], 2); + pDst[1] = L_shr_pos(L_add(pD, s1), 1); + s1 = L_sub(pD, L_shr_pos(s1, 1)); + + r1 = L_shr_pos(r1, 1); + r2 = L_shr_pos(r2, 1); + s1 = L_shr_pos(s1, 1); + s2 = L_shr_pos(s2, 1); + + /* combination */ + re = L_sub(r1, s2); + im = L_add(s1, r2); + vre = *pVecRe++; + vim = *pVecIm++; + cplxMpy_32_32(&pDst[3], &pDst[2], im, re, vre, vim); + + re = L_add(r1, s2); + im = L_sub(s1, r2); + + vre = *pVecRe++; + vim = *pVecIm++; + cplxMpy_32_32(&pDst[5], &pDst[4], im, re, vre, vim); + + pDst += 6; + pSrc += 2; + } + /* sample 0,1 are shifted right by 2 before output */ + /* sample 2,3 is shifted right by 1 and complex multiplied with (0.0,+1.0) */ + /* sample 4,5 is shifted right by 1 and complex multiplied with (-1.0,0.0) */ + r1 = L_add(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)); + r2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)), C31); + pD = L_shr_pos(pSrc[0], 2); + pDst[0] = L_shr_pos(L_add(pD, r1), 1); + r1 = L_sub(pD, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)); + s2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)), C31); + pD = L_shr_pos(pSrc[1], 2); + pDst[1] = L_shr_pos(L_add(pD, s1), 1); + s1 = L_sub(pD, L_shr_pos(s1, 1)); + + r1 = L_shr_pos(r1, 1); + r2 = L_shr_pos(r2, 1); + s1 = L_shr_pos(s1, 1); + s2 = L_shr_pos(s2, 1); + + /* combination */ + + pDst[2] = L_add(s1, r2); + move32(); + pDst[3] = L_sub(s2, r1); + move32(); + pDst[4] = L_negate(L_add(r1, s2)); + move32(); + pDst[5] = L_sub(r2, s1); + move32(); + /* Perform 3 times the fft of length 4. The input samples are at the address of aDst and the + output samples are at the address of pInput. The input vector for the fft of length 4 is built + of the interleaved samples in aDst, the output samples are stored consecutively at the address + of pInput. + */ + move16(); + move16(); + pSrc = aDst; + pDst = pInput; + FOR (i = 0; i < 3; i++) + { + /* inline FFT4 merged with incoming resorting loop */ + r1 = L_add(L_shr_pos(pSrc[0], 2), L_shr_pos(pSrc[12], 2)); /* Re A + Re B */ + r2 = L_add(L_shr_pos(pSrc[6], 2), L_shr_pos(pSrc[18], 2)); /* Re C + Re D */ + s1 = L_add(L_shr_pos(pSrc[1], 2), L_shr_pos(pSrc[13], 2)); /* Im A + Im B */ + s2 = L_add(L_shr_pos(pSrc[7], 2), L_shr_pos(pSrc[19], 2)); /* Im C + Im D */ + + pDst[0] = L_add(r1, r2); /* Re A' = Re A + Re B + Re C + Re D */ + pDst[1] = L_add(s1, s2); /* Im A' = Im A + Im B + Im C + Im D */ + + re = L_sub(r1, L_shr_pos(pSrc[12], 1)); /* Re A - Re B */ + im = L_sub(s1, L_shr_pos(pSrc[13], 1)); /* Im A - Im B */ + + pDst[12] = L_sub(r1, r2); /* Re C' = Re A + Re B - Re C - Re D */ + pDst[13] = L_sub(s1, s2); /* Im C' = Im A + Im B - Im C - Im D */ + + r2 = L_sub(r2, L_shr_pos(pSrc[18], 1)); /* Re C - Re D */ + s2 = L_sub(s2, L_shr_pos(pSrc[19], 1)); /* Im C - Im D */ + + pDst[6] = L_add(re, s2); /* Re B' = Re A - Re B + Im C - Im D */ + pDst[18] = L_sub(re, s2); /* Re D' = Re A - Re B - Im C + Im D */ + pDst[7] = L_sub(im, r2); /* Im B' = Im A - Im B - Re C + Re D */ + pDst[19] = L_add(im, r2); /* Im D' = Im A - Im B + Re C - Re D */ + + pSrc += 2; + pDst += 2; + } + + Dyn_Mem_Deluxe_Out(); +} + +#else /* CR8_G_ADD_75MS */ + +static void fft12(Word32 *pInput) +{ + Dyn_Mem_Deluxe_In(Word32 aDst[24]; Word32 * pSrc, *pDst; Counter i; Word32 r1, r2, s1, s2, pD; Word32 re, im; + Word16 vre, vim;); + + pSrc = pInput; + move16(); + pDst = aDst; + move16(); + + /* First 3*2 samples are shifted right by 2 before output */ + r1 = L_add(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)); + r2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)), C31); + pD = L_shr_pos(pSrc[0], 2); + pDst[0] = L_shr_pos(L_add(pD, r1), 1); + r1 = L_sub(pD, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)); + s2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)), C31); + pD = L_shr_pos(pSrc[1], 2); + pDst[1] = L_shr_pos(L_add(pD, s1), 1); + s1 = L_sub(pD, L_shr_pos(s1, 1)); + + r1 = L_shr_pos(r1, 1); + r2 = L_shr_pos(r2, 1); + s1 = L_shr_pos(s1, 1); + s2 = L_shr_pos(s2, 1); + + /* combination */ + pDst[2] = L_sub(r1, s2); + pDst[3] = L_add(s1, r2); + pDst[4] = L_add(r1, s2); + pDst[5] = L_sub(s1, r2); + pSrc += 2; + pDst += 6; + + vre = add(0x6eda, 0); + vim = add(0x4000, 0); + + FOR (i = 0; i < 2; i++) + { + /* sample 0,1 are shifted right by 2 before output */ + /* sample 2,3 4,5 are shifted right by 1 and complex multiplied before output */ + + r1 = L_add(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)); + r2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)), C31); + pD = L_shr_pos(pSrc[0], 2); + pDst[0] = L_shr_pos(L_add(pD, r1), 1); + r1 = L_sub(pD, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)); + s2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)), C31); + pD = L_shr_pos(pSrc[1], 2); + pDst[1] = L_shr_pos(L_add(pD, s1), 1); + s1 = L_sub(pD, L_shr_pos(s1, 1)); + + r1 = L_shr_pos(r1, 1); + r2 = L_shr_pos(r2, 1); + s1 = L_shr_pos(s1, 1); + s2 = L_shr_pos(s2, 1); + + /* combination */ + re = L_sub(r1, s2); + im = L_add(s1, r2); + cplxMpy_32_16(&pDst[3], &pDst[2], im, re, vre, vim); + re = L_add(r1, s2); + im = L_sub(s1, r2); + vre = add(0x4000, 0); + if (i == 1) + vre = negate(vre); /* 0xC000 */ + if (i == 0) + vim = add(0x6eda, 0); + cplxMpy_32_16(&pDst[5], &pDst[4], im, re, vre, vim); + + pDst += 6; + pSrc += 2; + } + /* sample 0,1 are shifted right by 2 before output */ + /* sample 2,3 is shifted right by 1 and complex multiplied with (0.0,+1.0) */ + /* sample 4,5 is shifted right by 1 and complex multiplied with (-1.0,0.0) */ + r1 = L_add(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)); + r2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[8], 2), L_shr_pos(pSrc[16], 2)), C31); + pD = L_shr_pos(pSrc[0], 2); + pDst[0] = L_shr_pos(L_add(pD, r1), 1); + r1 = L_sub(pD, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)); + s2 = Mpy_32_xx(L_sub(L_shr_pos(pSrc[9], 2), L_shr_pos(pSrc[17], 2)), C31); + pD = L_shr_pos(pSrc[1], 2); + pDst[1] = L_shr_pos(L_add(pD, s1), 1); + s1 = L_sub(pD, L_shr_pos(s1, 1)); + + r1 = L_shr_pos(r1, 1); + r2 = L_shr_pos(r2, 1); + s1 = L_shr_pos(s1, 1); + s2 = L_shr_pos(s2, 1); + + /* combination */ + + pDst[2] = L_add(s1, r2); + move32(); + pDst[3] = L_sub(s2, r1); + move32(); + pDst[4] = L_negate(L_add(r1, s2)); + move32(); + pDst[5] = L_sub(r2, s1); + move32(); + /* Perform 3 times the fft of length 4. The input samples are at the address of aDst and the + output samples are at the address of pInput. The input vector for the fft of length 4 is built + of the interleaved samples in aDst, the output samples are stored consecutively at the address + of pInput. + */ + move16(); + move16(); + pSrc = aDst; + pDst = pInput; + FOR (i = 0; i < 3; i++) + { + /* inline FFT4 merged with incoming resorting loop */ + r1 = L_add(L_shr_pos(pSrc[0], 2), L_shr_pos(pSrc[12], 2)); /* Re A + Re B */ + r2 = L_add(L_shr_pos(pSrc[6], 2), L_shr_pos(pSrc[18], 2)); /* Re C + Re D */ + s1 = L_add(L_shr_pos(pSrc[1], 2), L_shr_pos(pSrc[13], 2)); /* Im A + Im B */ + s2 = L_add(L_shr_pos(pSrc[7], 2), L_shr_pos(pSrc[19], 2)); /* Im C + Im D */ + + pDst[0] = L_add(r1, r2); /* Re A' = Re A + Re B + Re C + Re D */ + pDst[1] = L_add(s1, s2); /* Im A' = Im A + Im B + Im C + Im D */ + + re = L_sub(r1, L_shr_pos(pSrc[12], 1)); /* Re A - Re B */ + im = L_sub(s1, L_shr_pos(pSrc[13], 1)); /* Im A - Im B */ + + pDst[12] = L_sub(r1, r2); /* Re C' = Re A + Re B - Re C - Re D */ + pDst[13] = L_sub(s1, s2); /* Im C' = Im A + Im B - Im C - Im D */ + + r2 = L_sub(r2, L_shr_pos(pSrc[18], 1)); /* Re C - Re D */ + s2 = L_sub(s2, L_shr_pos(pSrc[19], 1)); /* Im C - Im D */ + + pDst[6] = L_add(re, s2); /* Re B' = Re A - Re B + Im C - Im D */ + pDst[18] = L_sub(re, s2); /* Re D' = Re A - Re B - Im C + Im D */ + pDst[7] = L_sub(im, r2); /* Im B' = Im A - Im B - Re C + Re D */ + pDst[19] = L_add(im, r2); /* Im D' = Im A - Im B + Re C - Re D */ + + pSrc += 2; + pDst += 2; + } + + Dyn_Mem_Deluxe_Out(); +} + +#endif + +/** + * \brief Function performs a complex 16-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR16 bits. + * + * WOPS with 32x16 bit multiplications (scale on ): 288 cycles + * WOPS with 32x16 bit multiplications (scale off): 256 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + + +static void fft16(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 x0, x1, x2, x3, x4, x5, x6, x7; Word32 t0, t1, t2, t3, t4, t5, t6, t7; + Word32 y00, y01, y02, y03, y04, y05, y06, y07; Word32 y08, y09, y10, y11, y12, y13, y14, y15; + Word32 y16, y17, y18, y19, y20, y21, y22, y23; Word32 y24, y25, y26, y27, y28, y29, y30, y31;); + + x0 = L_shr_pos(re[s * 0], SCALEFACTOR16); + x1 = L_shr_pos(im[s * 0], SCALEFACTOR16); + x2 = L_shr_pos(re[s * 4], SCALEFACTOR16); + x3 = L_shr_pos(im[s * 4], SCALEFACTOR16); + x4 = L_shr_pos(re[s * 8], SCALEFACTOR16); + x5 = L_shr_pos(im[s * 8], SCALEFACTOR16); + x6 = L_shr_pos(re[s * 12], SCALEFACTOR16); + x7 = L_shr_pos(im[s * 12], SCALEFACTOR16); + + /* Pre-additions */ + t0 = L_add(x0, x4); + t2 = L_sub(x0, x4); + t1 = L_add(x1, x5); + t3 = L_sub(x1, x5); + t4 = L_add(x2, x6); + t7 = L_sub(x2, x6); + t5 = L_add(x7, x3); + t6 = L_sub(x7, x3); + + /* Post-additions */ + y00 = L_add(t0, t4); + y01 = L_add(t1, t5); + y02 = L_sub(t2, t6); + y03 = L_sub(t3, t7); + y04 = L_sub(t0, t4); + y05 = L_sub(t1, t5); + y06 = L_add(t2, t6); + y07 = L_add(t3, t7); + + x0 = L_shr_pos(re[s * 1], SCALEFACTOR16); + x1 = L_shr_pos(im[s * 1], SCALEFACTOR16); + x2 = L_shr_pos(re[s * 5], SCALEFACTOR16); + x3 = L_shr_pos(im[s * 5], SCALEFACTOR16); + x4 = L_shr_pos(re[s * 9], SCALEFACTOR16); + x5 = L_shr_pos(im[s * 9], SCALEFACTOR16); + x6 = L_shr_pos(re[s * 13], SCALEFACTOR16); + x7 = L_shr_pos(im[s * 13], SCALEFACTOR16); + + /* Pre-additions */ + t0 = L_add(x0, x4); + t2 = L_sub(x0, x4); + t1 = L_add(x1, x5); + t3 = L_sub(x1, x5); + t4 = L_add(x2, x6); + t7 = L_sub(x2, x6); + t5 = L_add(x7, x3); + t6 = L_sub(x7, x3); + + /* Post-additions */ + y08 = L_add(t0, t4); + y09 = L_add(t1, t5); + y10 = L_sub(t2, t6); + y11 = L_sub(t3, t7); + y12 = L_sub(t0, t4); + y13 = L_sub(t1, t5); + y14 = L_add(t2, t6); + y15 = L_add(t3, t7); + + x0 = L_shr_pos(re[s * 2], SCALEFACTOR16); + x1 = L_shr_pos(im[s * 2], SCALEFACTOR16); + x2 = L_shr_pos(re[s * 6], SCALEFACTOR16); + x3 = L_shr_pos(im[s * 6], SCALEFACTOR16); + x4 = L_shr_pos(re[s * 10], SCALEFACTOR16); + x5 = L_shr_pos(im[s * 10], SCALEFACTOR16); + x6 = L_shr_pos(re[s * 14], SCALEFACTOR16); + x7 = L_shr_pos(im[s * 14], SCALEFACTOR16); + + /* Pre-additions */ + t0 = L_add(x0, x4); + t2 = L_sub(x0, x4); + t1 = L_add(x1, x5); + t3 = L_sub(x1, x5); + t4 = L_add(x2, x6); + t7 = L_sub(x2, x6); + t5 = L_add(x7, x3); + t6 = L_sub(x7, x3); + + /* Post-additions */ + y16 = L_add(t0, t4); + y17 = L_add(t1, t5); + y18 = L_sub(t2, t6); + y19 = L_sub(t3, t7); + y20 = L_sub(t1, t5); + y21 = L_sub(t4, t0); + y22 = L_add(t2, t6); + y23 = L_add(t3, t7); + + x0 = L_shr_pos(re[s * 3], SCALEFACTOR16); + x1 = L_shr_pos(im[s * 3], SCALEFACTOR16); + x2 = L_shr_pos(re[s * 7], SCALEFACTOR16); + x3 = L_shr_pos(im[s * 7], SCALEFACTOR16); + x4 = L_shr_pos(re[s * 11], SCALEFACTOR16); + x5 = L_shr_pos(im[s * 11], SCALEFACTOR16); + x6 = L_shr_pos(re[s * 15], SCALEFACTOR16); + x7 = L_shr_pos(im[s * 15], SCALEFACTOR16); + + /* Pre-additions */ + t0 = L_add(x0, x4); + t2 = L_sub(x0, x4); + t1 = L_add(x1, x5); + t3 = L_sub(x1, x5); + t4 = L_add(x2, x6); + t7 = L_sub(x2, x6); + t5 = L_add(x7, x3); + t6 = L_sub(x7, x3); + + /* Post-additions */ + y24 = L_add(t0, t4); + y25 = L_add(t1, t5); + y26 = L_sub(t2, t6); + y27 = L_sub(t3, t7); + y28 = L_sub(t0, t4); + y29 = L_sub(t1, t5); + y30 = L_add(t2, t6); + y31 = L_add(t3, t7); + + /* rotation */ + + x0 = Mpy_32_xx(y22, C162); + x1 = Mpy_32_xx(y23, C162); + y22 = L_sub(x0, x1); + y23 = L_add(x0, x1); + + x0 = Mpy_32_xx(y28, C162); + x1 = Mpy_32_xx(y29, C162); + y28 = L_sub(x0, x1); + y29 = L_add(x0, x1); + + x0 = Mpy_32_xx(y12, C161); + x1 = Mpy_32_xx(y13, C161); + y12 = L_add(x0, x1); + y13 = L_sub(x1, x0); + + x0 = Mpy_32_xx(y18, C161); + x1 = Mpy_32_xx(y19, C161); + y18 = L_add(x0, x1); + y19 = L_sub(x1, x0); + + x0 = Mpy_32_xx(y10, C163); + x1 = Mpy_32_xx(y11, C166); + x2 = Mpy_32_xx(y10, C166); + x3 = Mpy_32_xx(y11, C163); + y10 = L_sub(x0, x1); + y11 = L_add(x2, x3); + + x0 = Mpy_32_xx(y14, C165); + x1 = Mpy_32_xx(y15, C164); + x2 = Mpy_32_xx(y14, C164); + x3 = Mpy_32_xx(y15, C165); + y14 = L_sub(x0, x1); + y15 = L_add(x2, x3); + + x0 = Mpy_32_xx(y26, C165); + x1 = Mpy_32_xx(y27, C164); + x2 = Mpy_32_xx(y26, C164); + x3 = Mpy_32_xx(y27, C165); + y26 = L_sub(x0, x1); + y27 = L_add(x2, x3); + + x0 = Mpy_32_xx(y30, C164); + x1 = Mpy_32_xx(y31, C165); + x2 = Mpy_32_xx(y30, C165); + x3 = Mpy_32_xx(y31, C164); + y30 = L_sub(x0, x1); + y31 = L_add(x2, x3); + + /* Pre-additions */ + + t0 = L_add(y00, y16); + t2 = L_sub(y00, y16); + t1 = L_add(y01, y17); + t3 = L_sub(y01, y17); + t4 = L_add(y08, y24); + t7 = L_sub(y08, y24); + t5 = L_add(y25, y09); + t6 = L_sub(y25, y09); + + /* Post-additions */ + + re[s * 0] = L_add(t0, t4); + move32(); + im[s * 0] = L_add(t1, t5); + move32(); + re[s * 4] = L_sub(t2, t6); + move32(); + im[s * 4] = L_sub(t3, t7); + move32(); + re[s * 8] = L_sub(t0, t4); + move32(); + im[s * 8] = L_sub(t1, t5); + move32(); + re[s * 12] = L_add(t2, t6); + move32(); + im[s * 12] = L_add(t3, t7); + move32(); + + /* Pre-additions */ + + t0 = L_add(y02, y18); + t2 = L_sub(y02, y18); + t1 = L_add(y03, y19); + t3 = L_sub(y03, y19); + t4 = L_add(y10, y26); + t7 = L_sub(y10, y26); + t5 = L_add(y27, y11); + t6 = L_sub(y27, y11); + + /* Post-additions */ + + re[s * 1] = L_add(t0, t4); + move32(); + im[s * 1] = L_add(t1, t5); + move32(); + re[s * 5] = L_sub(t2, t6); + move32(); + im[s * 5] = L_sub(t3, t7); + move32(); + re[s * 9] = L_sub(t0, t4); + move32(); + im[s * 9] = L_sub(t1, t5); + move32(); + re[s * 13] = L_add(t2, t6); + move32(); + im[s * 13] = L_add(t3, t7); + move32(); + + /* Pre-additions */ + + t0 = L_add(y04, y20); + t2 = L_sub(y04, y20); + t1 = L_add(y05, y21); + t3 = L_sub(y05, y21); + t4 = L_add(y12, y28); + t7 = L_sub(y12, y28); + t5 = L_add(y29, y13); + t6 = L_sub(y29, y13); + + /* Post-additions */ + + re[s * 2] = L_add(t0, t4); + move32(); + im[s * 2] = L_add(t1, t5); + move32(); + re[s * 6] = L_sub(t2, t6); + move32(); + im[s * 6] = L_sub(t3, t7); + move32(); + re[s * 10] = L_sub(t0, t4); + move32(); + im[s * 10] = L_sub(t1, t5); + move32(); + re[s * 14] = L_add(t2, t6); + move32(); + im[s * 14] = L_add(t3, t7); + move32(); + + /* Pre-additions */ + + t0 = L_add(y06, y22); + t2 = L_sub(y06, y22); + t1 = L_add(y07, y23); + t3 = L_sub(y07, y23); + t4 = L_add(y14, y30); + t7 = L_sub(y14, y30); + t5 = L_add(y31, y15); + t6 = L_sub(y31, y15); + + /* Post-additions */ + + re[s * 3] = L_add(t0, t4); + move32(); + im[s * 3] = L_add(t1, t5); + move32(); + re[s * 7] = L_sub(t2, t6); + move32(); + im[s * 7] = L_sub(t3, t7); + move32(); + re[s * 11] = L_sub(t0, t4); + move32(); + im[s * 11] = L_sub(t1, t5); + move32(); + re[s * 15] = L_add(t2, t6); + move32(); + im[s * 15] = L_add(t3, t7); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 20-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR20 bits. + * + * WOPS with 32x16 bit multiplications: 432 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + +static void fft20(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 r1, r2, r3, r4; Word32 s1, s2, s3, s4; Word32 x0, x1, x2, x3, x4; + Word32 t, t0, t1, t2, t3, t4, t5, t6, t7; Word32 y00, y01, y02, y03, y04, y05, y06, y07, y08, y09; + Word32 y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + Word32 y20, y21, y22, y23, y24, y25, y26, y27, y28, y29; + Word32 y30, y31, y32, y33, y34, y35, y36, y37, y38, y39;); + + /* 1. FFT5 stage */ + + /* real part */ + x0 = L_shr_pos(re[s * 0], SCALEFACTOR20); + x1 = L_shr_pos(re[s * 16], SCALEFACTOR20); + x2 = L_shr_pos(re[s * 12], SCALEFACTOR20); + x3 = L_shr_pos(re[s * 8], SCALEFACTOR20); + x4 = L_shr_pos(re[s * 4], SCALEFACTOR20); + + r1 = L_add(x1, x4); + r4 = L_sub(x1, x4); + r3 = L_add(x2, x3); + r2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y00 = L_add(x0, r1); + r1 = L_add(y00, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 0], SCALEFACTOR20); + x1 = L_shr_pos(im[s * 16], SCALEFACTOR20); + x2 = L_shr_pos(im[s * 12], SCALEFACTOR20); + x3 = L_shr_pos(im[s * 8], SCALEFACTOR20); + x4 = L_shr_pos(im[s * 4], SCALEFACTOR20); + + s1 = L_add(x1, x4); + s4 = L_sub(x1, x4); + s3 = L_add(x2, x3); + s2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y01 = L_add(x0, s1); + s1 = L_add(y01, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y08 = L_add(r1, s2); + y32 = L_sub(r1, s2); + y16 = L_sub(r3, s4); + y24 = L_add(r3, s4); + + y09 = L_sub(s1, r2); + y33 = L_add(s1, r2); + y17 = L_add(s3, r4); + y25 = L_sub(s3, r4); + + /* 2. FFT5 stage */ + + /* real part */ + x0 = L_shr_pos(re[s * 5], SCALEFACTOR20); + x1 = L_shr_pos(re[s * 1], SCALEFACTOR20); + x2 = L_shr_pos(re[s * 17], SCALEFACTOR20); + x3 = L_shr_pos(re[s * 13], SCALEFACTOR20); + x4 = L_shr_pos(re[s * 9], SCALEFACTOR20); + + r1 = L_add(x1, x4); + r4 = L_sub(x1, x4); + r3 = L_add(x2, x3); + r2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y02 = L_add(x0, r1); + r1 = L_add(y02, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 5], SCALEFACTOR20); + x1 = L_shr_pos(im[s * 1], SCALEFACTOR20); + x2 = L_shr_pos(im[s * 17], SCALEFACTOR20); + x3 = L_shr_pos(im[s * 13], SCALEFACTOR20); + x4 = L_shr_pos(im[s * 9], SCALEFACTOR20); + + s1 = L_add(x1, x4); + s4 = L_sub(x1, x4); + s3 = L_add(x2, x3); + s2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y03 = L_add(x0, s1); + s1 = L_add(y03, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y10 = L_add(r1, s2); + y34 = L_sub(r1, s2); + y18 = L_sub(r3, s4); + y26 = L_add(r3, s4); + + y11 = L_sub(s1, r2); + y35 = L_add(s1, r2); + y19 = L_add(s3, r4); + y27 = L_sub(s3, r4); + + /* 3. FFT5 stage */ + + /* real part */ + x0 = L_shr_pos(re[s * 10], SCALEFACTOR20); + x1 = L_shr_pos(re[s * 6], SCALEFACTOR20); + x2 = L_shr_pos(re[s * 2], SCALEFACTOR20); + x3 = L_shr_pos(re[s * 18], SCALEFACTOR20); + x4 = L_shr_pos(re[s * 14], SCALEFACTOR20); + + r1 = L_add(x1, x4); + r4 = L_sub(x1, x4); + r3 = L_add(x2, x3); + r2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y04 = L_add(x0, r1); + r1 = L_add(y04, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 10], SCALEFACTOR20); + x1 = L_shr_pos(im[s * 6], SCALEFACTOR20); + x2 = L_shr_pos(im[s * 2], SCALEFACTOR20); + x3 = L_shr_pos(im[s * 18], SCALEFACTOR20); + x4 = L_shr_pos(im[s * 14], SCALEFACTOR20); + + s1 = L_add(x1, x4); + s4 = L_sub(x1, x4); + s3 = L_add(x2, x3); + s2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y05 = L_add(x0, s1); + s1 = L_add(y05, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y12 = L_add(r1, s2); + y36 = L_sub(r1, s2); + y20 = L_sub(r3, s4); + y28 = L_add(r3, s4); + + y13 = L_sub(s1, r2); + y37 = L_add(s1, r2); + y21 = L_add(s3, r4); + y29 = L_sub(s3, r4); + + /* 4. FFT5 stage */ + + /* real part */ + x0 = L_shr_pos(re[s * 15], SCALEFACTOR20); + x1 = L_shr_pos(re[s * 11], SCALEFACTOR20); + x2 = L_shr_pos(re[s * 7], SCALEFACTOR20); + x3 = L_shr_pos(re[s * 3], SCALEFACTOR20); + x4 = L_shr_pos(re[s * 19], SCALEFACTOR20); + + r1 = L_add(x1, x4); + r4 = L_sub(x1, x4); + r3 = L_add(x2, x3); + r2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y06 = L_add(x0, r1); + r1 = L_add(y06, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + x0 = L_shr_pos(im[s * 15], SCALEFACTOR20); + x1 = L_shr_pos(im[s * 11], SCALEFACTOR20); + x2 = L_shr_pos(im[s * 7], SCALEFACTOR20); + x3 = L_shr_pos(im[s * 3], SCALEFACTOR20); + x4 = L_shr_pos(im[s * 19], SCALEFACTOR20); + + s1 = L_add(x1, x4); + s4 = L_sub(x1, x4); + s3 = L_add(x2, x3); + s2 = L_sub(x2, x3); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y07 = L_add(x0, s1); + s1 = L_add(y07, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y14 = L_add(r1, s2); + y38 = L_sub(r1, s2); + y22 = L_sub(r3, s4); + y30 = L_add(r3, s4); + + y15 = L_sub(s1, r2); + y39 = L_add(s1, r2); + y23 = L_add(s3, r4); + y31 = L_sub(s3, r4); + + /* 1. FFT4 stage */ + + /* Pre-additions */ + t0 = L_add(y00, y04); + t2 = L_sub(y00, y04); + t1 = L_add(y01, y05); + t3 = L_sub(y01, y05); + t4 = L_add(y02, y06); + t7 = L_sub(y02, y06); + t5 = L_add(y07, y03); + t6 = L_sub(y07, y03); + + /* Post-additions */ + re[s * 0] = L_add(t0, t4); + move32(); + im[s * 0] = L_add(t1, t5); + move32(); + re[s * 5] = L_sub(t2, t6); + move32(); + im[s * 5] = L_sub(t3, t7); + move32(); + re[s * 10] = L_sub(t0, t4); + move32(); + im[s * 10] = L_sub(t1, t5); + move32(); + re[s * 15] = L_add(t2, t6); + move32(); + im[s * 15] = L_add(t3, t7); + move32(); + + /* 2. FFT4 stage */ + + /* Pre-additions */ + t0 = L_add(y08, y12); + t2 = L_sub(y08, y12); + t1 = L_add(y09, y13); + t3 = L_sub(y09, y13); + t4 = L_add(y10, y14); + t7 = L_sub(y10, y14); + t5 = L_add(y15, y11); + t6 = L_sub(y15, y11); + + /* Post-additions */ + re[s * 4] = L_add(t0, t4); + move32(); + im[s * 4] = L_add(t1, t5); + move32(); + re[s * 9] = L_sub(t2, t6); + move32(); + im[s * 9] = L_sub(t3, t7); + move32(); + re[s * 14] = L_sub(t0, t4); + move32(); + im[s * 14] = L_sub(t1, t5); + move32(); + re[s * 19] = L_add(t2, t6); + move32(); + im[s * 19] = L_add(t3, t7); + move32(); + + /* 3. FFT4 stage */ + + /* Pre-additions */ + t0 = L_add(y16, y20); + t2 = L_sub(y16, y20); + t1 = L_add(y17, y21); + t3 = L_sub(y17, y21); + t4 = L_add(y18, y22); + t7 = L_sub(y18, y22); + t5 = L_add(y23, y19); + t6 = L_sub(y23, y19); + + /* Post-additions */ + re[s * 8] = L_add(t0, t4); + move32(); + im[s * 8] = L_add(t1, t5); + move32(); + re[s * 13] = L_sub(t2, t6); + move32(); + im[s * 13] = L_sub(t3, t7); + move32(); + re[s * 18] = L_sub(t0, t4); + move32(); + im[s * 18] = L_sub(t1, t5); + move32(); + re[s * 3] = L_add(t2, t6); + move32(); + im[s * 3] = L_add(t3, t7); + move32(); + + /* 4. FFT4 stage */ + + /* Pre-additions */ + t0 = L_add(y24, y28); + t2 = L_sub(y24, y28); + t1 = L_add(y25, y29); + t3 = L_sub(y25, y29); + t4 = L_add(y26, y30); + t7 = L_sub(y26, y30); + t5 = L_add(y31, y27); + t6 = L_sub(y31, y27); + + /* Post-additions */ + re[s * 12] = L_add(t0, t4); + move32(); + im[s * 12] = L_add(t1, t5); + move32(); + re[s * 17] = L_sub(t2, t6); + move32(); + im[s * 17] = L_sub(t3, t7); + move32(); + re[s * 2] = L_sub(t0, t4); + move32(); + im[s * 2] = L_sub(t1, t5); + move32(); + re[s * 7] = L_add(t2, t6); + move32(); + im[s * 7] = L_add(t3, t7); + move32(); + + /* 5. FFT4 stage */ + + /* Pre-additions */ + t0 = L_add(y32, y36); + t2 = L_sub(y32, y36); + t1 = L_add(y33, y37); + t3 = L_sub(y33, y37); + t4 = L_add(y34, y38); + t7 = L_sub(y34, y38); + t5 = L_add(y39, y35); + t6 = L_sub(y39, y35); + + /* Post-additions */ + re[s * 16] = L_add(t0, t4); + move32(); + im[s * 16] = L_add(t1, t5); + move32(); + re[s * 1] = L_sub(t2, t6); + move32(); + im[s * 1] = L_sub(t3, t7); + move32(); + re[s * 6] = L_sub(t0, t4); + move32(); + im[s * 6] = L_sub(t1, t5); + move32(); + re[s * 11] = L_add(t2, t6); + move32(); + im[s * 11] = L_add(t3, t7); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 30-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR30 bits. + * + * WOPS with 32x16 bit multiplications: 828 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + +static void fft30(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 t; Word32 r1, r2, r3, r4; Word32 s1, s2, s3, s4; + Word32 x00, x01, x02, x03, x04, x05, x06, x07, x08, x09; + Word32 x10, x11, x12, x13, x14, x15, x16, x17, x18, x19; + Word32 x20, x21, x22, x23, x24, x25, x26, x27, x28, x29; + + Word32 y00, y01, y02, y03, y04, y05, y06, y07, y08, y09; + Word32 y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + Word32 y20, y21, y22, y23, y24, y25, y26, y27, y28, y29; + + Word32 z00, z01, z02, z03, z04, z05, z06, z07, z08, z09; + Word32 z10, z11, z12, z13, z14, z15, z16, z17, z18, z19; + Word32 z20, z21, z22, z23, z24, z25, z26, z27, z28, z29; + Word32 z30, z31, z32, z33, z34, z35, z36, z37, z38, z39; + Word32 z40, z41, z42, z43, z44, z45, z46, z47, z48, z49; + Word32 z50, z51, z52, z53, z54, z55, z56, z57, z58, z59; + + Word32 * rel, *reh, *iml, *imh;); + + rel = &re[s * 0]; + reh = &re[s * 15]; + iml = &im[s * 0]; + imh = &im[s * 15]; + + /* 1. FFT15 stage */ + x00 = L_shr_pos(re[s * 0], SCALEFACTOR30_1); + x01 = L_shr_pos(im[s * 0], SCALEFACTOR30_1); + x02 = L_shr_pos(re[s * 18], SCALEFACTOR30_1); + x03 = L_shr_pos(im[s * 18], SCALEFACTOR30_1); + x04 = L_shr_pos(re[s * 6], SCALEFACTOR30_1); + x05 = L_shr_pos(im[s * 6], SCALEFACTOR30_1); + x06 = L_shr_pos(re[s * 24], SCALEFACTOR30_1); + x07 = L_shr_pos(im[s * 24], SCALEFACTOR30_1); + x08 = L_shr_pos(re[s * 12], SCALEFACTOR30_1); + x09 = L_shr_pos(im[s * 12], SCALEFACTOR30_1); + + x10 = L_shr_pos(re[s * 20], SCALEFACTOR30_1); + x11 = L_shr_pos(im[s * 20], SCALEFACTOR30_1); + x12 = L_shr_pos(re[s * 8], SCALEFACTOR30_1); + x13 = L_shr_pos(im[s * 8], SCALEFACTOR30_1); + x14 = L_shr_pos(re[s * 26], SCALEFACTOR30_1); + x15 = L_shr_pos(im[s * 26], SCALEFACTOR30_1); + x16 = L_shr_pos(re[s * 14], SCALEFACTOR30_1); + x17 = L_shr_pos(im[s * 14], SCALEFACTOR30_1); + x18 = L_shr_pos(re[s * 2], SCALEFACTOR30_1); + x19 = L_shr_pos(im[s * 2], SCALEFACTOR30_1); + + x20 = L_shr_pos(re[s * 10], SCALEFACTOR30_1); + x21 = L_shr_pos(im[s * 10], SCALEFACTOR30_1); + x22 = L_shr_pos(re[s * 28], SCALEFACTOR30_1); + x23 = L_shr_pos(im[s * 28], SCALEFACTOR30_1); + x24 = L_shr_pos(re[s * 16], SCALEFACTOR30_1); + x25 = L_shr_pos(im[s * 16], SCALEFACTOR30_1); + x26 = L_shr_pos(re[s * 4], SCALEFACTOR30_1); + x27 = L_shr_pos(im[s * 4], SCALEFACTOR30_1); + x28 = L_shr_pos(re[s * 22], SCALEFACTOR30_1); + x29 = L_shr_pos(im[s * 22], SCALEFACTOR30_1); + + /* 1. FFT5 stage */ + + /* real part */ + r1 = L_add(x02, x08); + r4 = L_sub(x02, x08); + r3 = L_add(x04, x06); + r2 = L_sub(x04, x06); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y00 = L_add(x00, r1); + r1 = L_add(y00, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x03, x09); + s4 = L_sub(x03, x09); + s3 = L_add(x05, x07); + s2 = L_sub(x05, x07); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y01 = L_add(x01, s1); + s1 = L_add(y01, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y02 = L_add(r1, s2); + y08 = L_sub(r1, s2); + y04 = L_sub(r3, s4); + y06 = L_add(r3, s4); + + y03 = L_sub(s1, r2); + y09 = L_add(s1, r2); + y05 = L_add(s3, r4); + y07 = L_sub(s3, r4); + + /* 2. FFT5 stage */ + + /* real part */ + r1 = L_add(x12, x18); + r4 = L_sub(x12, x18); + r3 = L_add(x14, x16); + r2 = L_sub(x14, x16); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y10 = L_add(x10, r1); + r1 = L_add(y10, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x13, x19); + s4 = L_sub(x13, x19); + s3 = L_add(x15, x17); + s2 = L_sub(x15, x17); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y11 = L_add(x11, s1); + s1 = L_add(y11, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y12 = L_add(r1, s2); + y18 = L_sub(r1, s2); + y14 = L_sub(r3, s4); + y16 = L_add(r3, s4); + + y13 = L_sub(s1, r2); + y19 = L_add(s1, r2); + y15 = L_add(s3, r4); + y17 = L_sub(s3, r4); + + /* 3. FFT5 stage */ + + /* real part */ + r1 = L_add(x22, x28); + r4 = L_sub(x22, x28); + r3 = L_add(x24, x26); + r2 = L_sub(x24, x26); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y20 = L_add(x20, r1); + r1 = L_add(y20, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x23, x29); + s4 = L_sub(x23, x29); + s3 = L_add(x25, x27); + s2 = L_sub(x25, x27); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y21 = L_add(x21, s1); + s1 = L_add(y21, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y22 = L_add(r1, s2); + y28 = L_sub(r1, s2); + y24 = L_sub(r3, s4); + y26 = L_add(r3, s4); + + y23 = L_sub(s1, r2); + y29 = L_add(s1, r2); + y25 = L_add(s3, r4); + y27 = L_sub(s3, r4); + + /* 1. FFT3 stage */ + + /* real part */ + r1 = L_add(y10, y20); + r2 = Mpy_32_xx(L_sub(y10, y20), C31); + z00 = L_add(y00, r1); + r1 = L_sub(y00, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y11, y21); + s2 = Mpy_32_xx(L_sub(y11, y21), C31); + z01 = L_add(y01, s1); + s1 = L_sub(y01, L_shr_pos(s1, 1)); + + /* combination */ + z20 = L_sub(r1, s2); + z10 = L_add(r1, s2); + z21 = L_add(s1, r2); + z11 = L_sub(s1, r2); + + /* 2. FFT3 stage */ + + /* real part */ + r1 = L_add(y12, y22); + r2 = Mpy_32_xx(L_sub(y12, y22), C31); + z12 = L_add(y02, r1); + r1 = L_sub(y02, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y13, y23); + s2 = Mpy_32_xx(L_sub(y13, y23), C31); + z13 = L_add(y03, s1); + s1 = L_sub(y03, L_shr_pos(s1, 1)); + + /* combination */ + z02 = L_sub(r1, s2); + z22 = L_add(r1, s2); + z03 = L_add(s1, r2); + z23 = L_sub(s1, r2); + + /* 3. FFT3 stage */ + + /* real part */ + r1 = L_add(y14, y24); + r2 = Mpy_32_xx(L_sub(y14, y24), C31); + z24 = L_add(y04, r1); + r1 = L_sub(y04, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y15, y25); + s2 = Mpy_32_xx(L_sub(y15, y25), C31); + z25 = L_add(y05, s1); + s1 = L_sub(y05, L_shr_pos(s1, 1)); + + /* combination */ + z14 = L_sub(r1, s2); + z04 = L_add(r1, s2); + z15 = L_add(s1, r2); + z05 = L_sub(s1, r2); + + /* 4. FFT3 stage */ + + /* real part */ + r1 = L_add(y16, y26); + r2 = Mpy_32_xx(L_sub(y16, y26), C31); + z06 = L_add(y06, r1); + r1 = L_sub(y06, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y17, y27); + s2 = Mpy_32_xx(L_sub(y17, y27), C31); + z07 = L_add(y07, s1); + s1 = L_sub(y07, L_shr_pos(s1, 1)); + + /* combination */ + z26 = L_sub(r1, s2); + z16 = L_add(r1, s2); + z27 = L_add(s1, r2); + z17 = L_sub(s1, r2); + + /* 5. FFT3 stage */ + + /* real part */ + r1 = L_add(y18, y28); + r2 = Mpy_32_xx(L_sub(y18, y28), C31); + z18 = L_add(y08, r1); + r1 = L_sub(y08, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y19, y29); + s2 = Mpy_32_xx(L_sub(y19, y29), C31); + z19 = L_add(y09, s1); + s1 = L_sub(y09, L_shr_pos(s1, 1)); + + /* combination */ + z08 = L_sub(r1, s2); + z28 = L_add(r1, s2); + z09 = L_add(s1, r2); + z29 = L_sub(s1, r2); + + /* 2. FFT15 stage */ + x00 = L_shr_pos(re[s * 15], SCALEFACTOR30_1); + x01 = L_shr_pos(im[s * 15], SCALEFACTOR30_1); + x02 = L_shr_pos(re[s * 3], SCALEFACTOR30_1); + x03 = L_shr_pos(im[s * 3], SCALEFACTOR30_1); + x04 = L_shr_pos(re[s * 21], SCALEFACTOR30_1); + x05 = L_shr_pos(im[s * 21], SCALEFACTOR30_1); + x06 = L_shr_pos(re[s * 9], SCALEFACTOR30_1); + x07 = L_shr_pos(im[s * 9], SCALEFACTOR30_1); + x08 = L_shr_pos(re[s * 27], SCALEFACTOR30_1); + x09 = L_shr_pos(im[s * 27], SCALEFACTOR30_1); + + x10 = L_shr_pos(re[s * 5], SCALEFACTOR30_1); + x11 = L_shr_pos(im[s * 5], SCALEFACTOR30_1); + x12 = L_shr_pos(re[s * 23], SCALEFACTOR30_1); + x13 = L_shr_pos(im[s * 23], SCALEFACTOR30_1); + x14 = L_shr_pos(re[s * 11], SCALEFACTOR30_1); + x15 = L_shr_pos(im[s * 11], SCALEFACTOR30_1); + x16 = L_shr_pos(re[s * 29], SCALEFACTOR30_1); + x17 = L_shr_pos(im[s * 29], SCALEFACTOR30_1); + x18 = L_shr_pos(re[s * 17], SCALEFACTOR30_1); + x19 = L_shr_pos(im[s * 17], SCALEFACTOR30_1); + + x20 = L_shr_pos(re[s * 25], SCALEFACTOR30_1); + x21 = L_shr_pos(im[s * 25], SCALEFACTOR30_1); + x22 = L_shr_pos(re[s * 13], SCALEFACTOR30_1); + x23 = L_shr_pos(im[s * 13], SCALEFACTOR30_1); + x24 = L_shr_pos(re[s * 1], SCALEFACTOR30_1); + x25 = L_shr_pos(im[s * 1], SCALEFACTOR30_1); + x26 = L_shr_pos(re[s * 19], SCALEFACTOR30_1); + x27 = L_shr_pos(im[s * 19], SCALEFACTOR30_1); + x28 = L_shr_pos(re[s * 7], SCALEFACTOR30_1); + x29 = L_shr_pos(im[s * 7], SCALEFACTOR30_1); + + /* 1. FFT5 stage */ + + /* real part */ + r1 = L_add(x02, x08); + r4 = L_sub(x02, x08); + r3 = L_add(x04, x06); + r2 = L_sub(x04, x06); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y00 = L_add(x00, r1); + r1 = L_add(y00, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x03, x09); + s4 = L_sub(x03, x09); + s3 = L_add(x05, x07); + s2 = L_sub(x05, x07); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y01 = L_add(x01, s1); + s1 = L_add(y01, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y02 = L_add(r1, s2); + y08 = L_sub(r1, s2); + y04 = L_sub(r3, s4); + y06 = L_add(r3, s4); + + y03 = L_sub(s1, r2); + y09 = L_add(s1, r2); + y05 = L_add(s3, r4); + y07 = L_sub(s3, r4); + + /* 2. FFT5 stage */ + + /* real part */ + r1 = L_add(x12, x18); + r4 = L_sub(x12, x18); + r3 = L_add(x14, x16); + r2 = L_sub(x14, x16); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y10 = L_add(x10, r1); + r1 = L_add(y10, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x13, x19); + s4 = L_sub(x13, x19); + s3 = L_add(x15, x17); + s2 = L_sub(x15, x17); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y11 = L_add(x11, s1); + s1 = L_add(y11, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y12 = L_add(r1, s2); + y18 = L_sub(r1, s2); + y14 = L_sub(r3, s4); + y16 = L_add(r3, s4); + + y13 = L_sub(s1, r2); + y19 = L_add(s1, r2); + y15 = L_add(s3, r4); + y17 = L_sub(s3, r4); + + /* 3. FFT5 stage */ + + /* real part */ + r1 = L_add(x22, x28); + r4 = L_sub(x22, x28); + r3 = L_add(x24, x26); + r2 = L_sub(x24, x26); + t = Mpy_32_xx(L_sub(r1, r3), C54); + r1 = L_add(r1, r3); + y20 = L_add(x20, r1); + r1 = L_add(y20, (L_shl_pos(Mpy_32_xx(r1, C55), 1))); + r3 = L_sub(r1, t); + r1 = L_add(r1, t); + t = Mpy_32_xx((L_add(r4, r2)), C51); + r4 = L_add(t, L_shl_pos(Mpy_32_xx(r4, C52), 1)); + r2 = L_add(t, Mpy_32_xx(r2, C53)); + + /* imaginary part */ + s1 = L_add(x23, x29); + s4 = L_sub(x23, x29); + s3 = L_add(x25, x27); + s2 = L_sub(x25, x27); + t = Mpy_32_xx(L_sub(s1, s3), C54); + s1 = L_add(s1, s3); + y21 = L_add(x21, s1); + s1 = L_add(y21, L_shl_pos(Mpy_32_xx(s1, C55), 1)); + s3 = L_sub(s1, t); + s1 = L_add(s1, t); + t = Mpy_32_xx(L_add(s4, s2), C51); + s4 = L_add(t, L_shl_pos(Mpy_32_xx(s4, C52), 1)); + s2 = L_add(t, Mpy_32_xx(s2, C53)); + + /* combination */ + y22 = L_add(r1, s2); + y28 = L_sub(r1, s2); + y24 = L_sub(r3, s4); + y26 = L_add(r3, s4); + + y23 = L_sub(s1, r2); + y29 = L_add(s1, r2); + y25 = L_add(s3, r4); + y27 = L_sub(s3, r4); + + /* 1. FFT3 stage */ + + /* real part */ + r1 = L_add(y10, y20); + r2 = Mpy_32_xx(L_sub(y10, y20), C31); + z30 = L_add(y00, r1); + r1 = L_sub(y00, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y11, y21); + s2 = Mpy_32_xx(L_sub(y11, y21), C31); + z31 = L_add(y01, s1); + s1 = L_sub(y01, L_shr_pos(s1, 1)); + + /* combination */ + z50 = L_sub(r1, s2); + z40 = L_add(r1, s2); + z51 = L_add(s1, r2); + z41 = L_sub(s1, r2); + + /* 2. FFT3 stage */ + + /* real part */ + r1 = L_add(y12, y22); + r2 = Mpy_32_xx(L_sub(y12, y22), C31); + z42 = L_add(y02, r1); + r1 = L_sub(y02, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y13, y23); + s2 = Mpy_32_xx(L_sub(y13, y23), C31); + z43 = L_add(y03, s1); + s1 = L_sub(y03, L_shr_pos(s1, 1)); + + /* combination */ + z32 = L_sub(r1, s2); + z52 = L_add(r1, s2); + z33 = L_add(s1, r2); + z53 = L_sub(s1, r2); + + /* 3. FFT3 stage */ + + /* real part */ + r1 = L_add(y14, y24); + r2 = Mpy_32_xx(L_sub(y14, y24), C31); + z54 = L_add(y04, r1); + r1 = L_sub(y04, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y15, y25); + s2 = Mpy_32_xx(L_sub(y15, y25), C31); + z55 = L_add(y05, s1); + s1 = L_sub(y05, L_shr_pos(s1, 1)); + + /* combination */ + z44 = L_sub(r1, s2); + z34 = L_add(r1, s2); + z45 = L_add(s1, r2); + z35 = L_sub(s1, r2); + + /* 4. FFT3 stage */ + + /* real part */ + r1 = L_add(y16, y26); + r2 = Mpy_32_xx(L_sub(y16, y26), C31); + z36 = L_add(y06, r1); + r1 = L_sub(y06, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y17, y27); + s2 = Mpy_32_xx(L_sub(y17, y27), C31); + z37 = L_add(y07, s1); + s1 = L_sub(y07, L_shr_pos(s1, 1)); + + /* combination */ + z56 = L_sub(r1, s2); + z46 = L_add(r1, s2); + z57 = L_add(s1, r2); + z47 = L_sub(s1, r2); + + /* 5. FFT3 stage */ + + /* real part */ + r1 = L_add(y18, y28); + r2 = Mpy_32_xx(L_sub(y18, y28), C31); + z48 = L_add(y08, r1); + r1 = L_sub(y08, L_shr_pos(r1, 1)); + + /* imaginary part */ + s1 = L_add(y19, y29); + s2 = Mpy_32_xx(L_sub(y19, y29), C31); + z49 = L_add(y09, s1); + s1 = L_sub(y09, L_shr_pos(s1, 1)); + + /* combination */ + z38 = L_sub(r1, s2); + z58 = L_add(r1, s2); + z39 = L_add(s1, r2); + z59 = L_sub(s1, r2); + + /* 1. FFT2 stage */ + r1 = L_shr_pos(z00, SCALEFACTOR30_2); + r2 = L_shr_pos(z30, SCALEFACTOR30_2); + r3 = L_shr_pos(z01, SCALEFACTOR30_2); + r4 = L_shr_pos(z31, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 2. FFT2 stage */ + r1 = L_shr_pos(z16, SCALEFACTOR30_2); + r2 = L_shr_pos(z46, SCALEFACTOR30_2); + r3 = L_shr_pos(z17, SCALEFACTOR30_2); + r4 = L_shr_pos(z47, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 3. FFT2 stage */ + r1 = L_shr_pos(z02, SCALEFACTOR30_2); + r2 = L_shr_pos(z32, SCALEFACTOR30_2); + r3 = L_shr_pos(z03, SCALEFACTOR30_2); + r4 = L_shr_pos(z33, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 4. FFT2 stage */ + r1 = L_shr_pos(z18, SCALEFACTOR30_2); + r2 = L_shr_pos(z48, SCALEFACTOR30_2); + r3 = L_shr_pos(z19, SCALEFACTOR30_2); + r4 = L_shr_pos(z49, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 5. FFT2 stage */ + r1 = L_shr_pos(z04, SCALEFACTOR30_2); + r2 = L_shr_pos(z34, SCALEFACTOR30_2); + r3 = L_shr_pos(z05, SCALEFACTOR30_2); + r4 = L_shr_pos(z35, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 6. FFT2 stage */ + r1 = L_shr_pos(z20, SCALEFACTOR30_2); + r2 = L_shr_pos(z50, SCALEFACTOR30_2); + r3 = L_shr_pos(z21, SCALEFACTOR30_2); + r4 = L_shr_pos(z51, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 7. FFT2 stage */ + r1 = L_shr_pos(z06, SCALEFACTOR30_2); + r2 = L_shr_pos(z36, SCALEFACTOR30_2); + r3 = L_shr_pos(z07, SCALEFACTOR30_2); + r4 = L_shr_pos(z37, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 8. FFT2 stage */ + r1 = L_shr_pos(z22, SCALEFACTOR30_2); + r2 = L_shr_pos(z52, SCALEFACTOR30_2); + r3 = L_shr_pos(z23, SCALEFACTOR30_2); + r4 = L_shr_pos(z53, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 9. FFT2 stage */ + r1 = L_shr_pos(z08, SCALEFACTOR30_2); + r2 = L_shr_pos(z38, SCALEFACTOR30_2); + r3 = L_shr_pos(z09, SCALEFACTOR30_2); + r4 = L_shr_pos(z39, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 10. FFT2 stage */ + r1 = L_shr_pos(z24, SCALEFACTOR30_2); + r2 = L_shr_pos(z54, SCALEFACTOR30_2); + r3 = L_shr_pos(z25, SCALEFACTOR30_2); + r4 = L_shr_pos(z55, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 11. FFT2 stage */ + r1 = L_shr_pos(z10, SCALEFACTOR30_2); + r2 = L_shr_pos(z40, SCALEFACTOR30_2); + r3 = L_shr_pos(z11, SCALEFACTOR30_2); + r4 = L_shr_pos(z41, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 12. FFT2 stage */ + r1 = L_shr_pos(z26, SCALEFACTOR30_2); + r2 = L_shr_pos(z56, SCALEFACTOR30_2); + r3 = L_shr_pos(z27, SCALEFACTOR30_2); + r4 = L_shr_pos(z57, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 13. FFT2 stage */ + r1 = L_shr_pos(z12, SCALEFACTOR30_2); + r2 = L_shr_pos(z42, SCALEFACTOR30_2); + r3 = L_shr_pos(z13, SCALEFACTOR30_2); + r4 = L_shr_pos(z43, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 14. FFT2 stage */ + r1 = L_shr_pos(z28, SCALEFACTOR30_2); + r2 = L_shr_pos(z58, SCALEFACTOR30_2); + r3 = L_shr_pos(z29, SCALEFACTOR30_2); + r4 = L_shr_pos(z59, SCALEFACTOR30_2); + *reh = L_add(r1, r2); + move32(); + *rel = L_sub(r1, r2); + move32(); + *imh = L_add(r3, r4); + move32(); + *iml = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + /* 15. FFT2 stage */ + r1 = L_shr_pos(z14, SCALEFACTOR30_2); + r2 = L_shr_pos(z44, SCALEFACTOR30_2); + r3 = L_shr_pos(z15, SCALEFACTOR30_2); + r4 = L_shr_pos(z45, SCALEFACTOR30_2); + *rel = L_add(r1, r2); + move32(); + *reh = L_sub(r1, r2); + move32(); + *iml = L_add(r3, r4); + move32(); + *imh = L_sub(r3, r4); + move32(); + rel += s, reh += s, iml += s; + imh += s; + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 32-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR32 bits. + * + * WOPS with 32x16 bit multiplications: 752 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + +static void fft32(Word32 *re, Word32 *im, Word16 s) +{ + Dyn_Mem_Deluxe_In(Word32 as, bs; Word32 x00, x01, x02, x03, x04, x05, x06, x07; + Word32 x08, x09, x10, x11, x12, x13, x14, x15; Word32 t00, t01, t02, t03, t04, t05, t06, t07; + Word32 t08, t09, t10, t11, t12, t13, t14, t15; Word32 s00, s01, s02, s03, s04, s05, s06, s07; + Word32 s08, s09, s10, s11, s12, s13, s14, s15; + + Word32 y00, y01, y02, y03, y04, y05, y06, y07; Word32 y08, y09, y10, y11, y12, y13, y14, y15; + Word32 y16, y17, y18, y19, y20, y21, y22, y23; Word32 y24, y25, y26, y27, y28, y29, y30, y31; + Word32 y32, y33, y34, y35, y36, y37, y38, y39; Word32 y40, y41, y42, y43, y44, y45, y46, y47; + Word32 y48, y49, y50, y51, y52, y53, y54, y55; Word32 y56, y57, y58, y59, y60, y61, y62, y63;); + + /* 1. FFT8 stage */ + x00 = L_shr_pos(re[s * 0], SCALEFACTOR32_1); + x01 = L_shr_pos(im[s * 0], SCALEFACTOR32_1); + x02 = L_shr_pos(re[s * 4], SCALEFACTOR32_1); + x03 = L_shr_pos(im[s * 4], SCALEFACTOR32_1); + x04 = L_shr_pos(re[s * 8], SCALEFACTOR32_1); + x05 = L_shr_pos(im[s * 8], SCALEFACTOR32_1); + x06 = L_shr_pos(re[s * 12], SCALEFACTOR32_1); + x07 = L_shr_pos(im[s * 12], SCALEFACTOR32_1); + x08 = L_shr_pos(re[s * 16], SCALEFACTOR32_1); + x09 = L_shr_pos(im[s * 16], SCALEFACTOR32_1); + x10 = L_shr_pos(re[s * 20], SCALEFACTOR32_1); + x11 = L_shr_pos(im[s * 20], SCALEFACTOR32_1); + x12 = L_shr_pos(re[s * 24], SCALEFACTOR32_1); + x13 = L_shr_pos(im[s * 24], SCALEFACTOR32_1); + x14 = L_shr_pos(re[s * 28], SCALEFACTOR32_1); + x15 = L_shr_pos(im[s * 28], SCALEFACTOR32_1); + + t00 = L_add(x00, x08); + t02 = L_sub(x00, x08); + t01 = L_add(x01, x09); + t03 = L_sub(x01, x09); + t04 = L_add(x02, x10); + t06 = L_sub(x02, x10); + t05 = L_add(x03, x11); + t07 = L_sub(x03, x11); + t08 = L_add(x04, x12); + t10 = L_sub(x04, x12); + t09 = L_add(x05, x13); + t11 = L_sub(x05, x13); + t12 = L_add(x06, x14); + t14 = L_sub(x06, x14); + t13 = L_add(x07, x15); + t15 = L_sub(x07, x15); + + /* Pre-additions and core multiplications */ + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + t01 = L_add(t06, t14); + t02 = L_sub(t06, t14); + t00 = L_add(t07, t15); + t03 = L_sub(t07, t15); + + Mpy3_0(s12, s13, s14, s15, t00, t01, t02, t03); + + /* Post-additions */ + y00 = L_add(s00, s02); + y08 = L_sub(s00, s02); + y01 = L_add(s01, s03); + y09 = L_sub(s01, s03); + y04 = L_sub(s04, s06); + y12 = L_add(s04, s06); + y05 = L_sub(s05, s07); + y13 = L_add(s05, s07); + y06 = L_add(s08, s14); + y14 = L_sub(s08, s14); + y07 = L_add(s09, s15); + y15 = L_sub(s09, s15); + y02 = L_add(s10, s12); + y10 = L_sub(s10, s12); + y03 = L_add(s11, s13); + y11 = L_sub(s11, s13); + + /* 2. FFT8 stage */ + x00 = L_shr_pos(re[s * 1], SCALEFACTOR32_1); + x01 = L_shr_pos(im[s * 1], SCALEFACTOR32_1); + x02 = L_shr_pos(re[s * 5], SCALEFACTOR32_1); + x03 = L_shr_pos(im[s * 5], SCALEFACTOR32_1); + x04 = L_shr_pos(re[s * 9], SCALEFACTOR32_1); + x05 = L_shr_pos(im[s * 9], SCALEFACTOR32_1); + x06 = L_shr_pos(re[s * 13], SCALEFACTOR32_1); + x07 = L_shr_pos(im[s * 13], SCALEFACTOR32_1); + x08 = L_shr_pos(re[s * 17], SCALEFACTOR32_1); + x09 = L_shr_pos(im[s * 17], SCALEFACTOR32_1); + x10 = L_shr_pos(re[s * 21], SCALEFACTOR32_1); + x11 = L_shr_pos(im[s * 21], SCALEFACTOR32_1); + x12 = L_shr_pos(re[s * 25], SCALEFACTOR32_1); + x13 = L_shr_pos(im[s * 25], SCALEFACTOR32_1); + x14 = L_shr_pos(re[s * 29], SCALEFACTOR32_1); + x15 = L_shr_pos(im[s * 29], SCALEFACTOR32_1); + + t00 = L_add(x00, x08); + t02 = L_sub(x00, x08); + t01 = L_add(x01, x09); + t03 = L_sub(x01, x09); + t04 = L_add(x02, x10); + t06 = L_sub(x02, x10); + t05 = L_add(x03, x11); + t07 = L_sub(x03, x11); + t08 = L_add(x04, x12); + t10 = L_sub(x04, x12); + t09 = L_add(x05, x13); + t11 = L_sub(x05, x13); + t12 = L_add(x06, x14); + t14 = L_sub(x06, x14); + t13 = L_add(x07, x15); + t15 = L_sub(x07, x15); + + /* Pre-additions and core multiplications */ + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + t01 = L_add(t06, t14); + t02 = L_sub(t06, t14); + t00 = L_add(t07, t15); + t03 = L_sub(t07, t15); + + Mpy3_0(s12, s13, s14, s15, t00, t01, t02, t03); + + /* Post-additions */ + y16 = L_add(s00, s02); + y24 = L_sub(s00, s02); + y17 = L_add(s01, s03); + y25 = L_sub(s01, s03); + y20 = L_sub(s04, s06); + y28 = L_add(s04, s06); + y21 = L_sub(s05, s07); + y29 = L_add(s05, s07); + y22 = L_add(s08, s14); + y30 = L_sub(s08, s14); + y23 = L_add(s09, s15); + y31 = L_sub(s09, s15); + y18 = L_add(s10, s12); + y26 = L_sub(s10, s12); + y19 = L_add(s11, s13); + y27 = L_sub(s11, s13); + + /* 3. FFT8 stage */ + x00 = L_shr_pos(re[s * 2], SCALEFACTOR32_1); + x01 = L_shr_pos(im[s * 2], SCALEFACTOR32_1); + x02 = L_shr_pos(re[s * 6], SCALEFACTOR32_1); + x03 = L_shr_pos(im[s * 6], SCALEFACTOR32_1); + x04 = L_shr_pos(re[s * 10], SCALEFACTOR32_1); + x05 = L_shr_pos(im[s * 10], SCALEFACTOR32_1); + x06 = L_shr_pos(re[s * 14], SCALEFACTOR32_1); + x07 = L_shr_pos(im[s * 14], SCALEFACTOR32_1); + x08 = L_shr_pos(re[s * 18], SCALEFACTOR32_1); + x09 = L_shr_pos(im[s * 18], SCALEFACTOR32_1); + x10 = L_shr_pos(re[s * 22], SCALEFACTOR32_1); + x11 = L_shr_pos(im[s * 22], SCALEFACTOR32_1); + x12 = L_shr_pos(re[s * 26], SCALEFACTOR32_1); + x13 = L_shr_pos(im[s * 26], SCALEFACTOR32_1); + x14 = L_shr_pos(re[s * 30], SCALEFACTOR32_1); + x15 = L_shr_pos(im[s * 30], SCALEFACTOR32_1); + + t00 = L_add(x00, x08); + t02 = L_sub(x00, x08); + t01 = L_add(x01, x09); + t03 = L_sub(x01, x09); + t04 = L_add(x02, x10); + t06 = L_sub(x02, x10); + t05 = L_add(x03, x11); + t07 = L_sub(x03, x11); + t08 = L_add(x04, x12); + t10 = L_sub(x04, x12); + t09 = L_add(x05, x13); + t11 = L_sub(x05, x13); + t12 = L_add(x06, x14); + t14 = L_sub(x06, x14); + t13 = L_add(x07, x15); + t15 = L_sub(x07, x15); + + /* Pre-additions and core multiplications */ + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + t01 = L_add(t06, t14); + t02 = L_sub(t06, t14); + t00 = L_add(t07, t15); + t03 = L_sub(t07, t15); + + Mpy3_0(s12, s13, s14, s15, t00, t01, t02, t03); + + /* Post-additions */ + y32 = L_add(s00, s02); + y40 = L_sub(s00, s02); + y33 = L_add(s01, s03); + y41 = L_sub(s01, s03); + y36 = L_sub(s04, s06); + y44 = L_add(s04, s06); + y37 = L_sub(s05, s07); + y45 = L_add(s05, s07); + y38 = L_add(s08, s14); + y46 = L_sub(s08, s14); + y39 = L_add(s09, s15); + y47 = L_sub(s09, s15); + y34 = L_add(s10, s12); + y42 = L_sub(s10, s12); + y35 = L_add(s11, s13); + y43 = L_sub(s11, s13); + + /* 4. FFT8 stage */ + x00 = L_shr_pos(re[s * 3], SCALEFACTOR32_1); + x01 = L_shr_pos(im[s * 3], SCALEFACTOR32_1); + x02 = L_shr_pos(re[s * 7], SCALEFACTOR32_1); + x03 = L_shr_pos(im[s * 7], SCALEFACTOR32_1); + x04 = L_shr_pos(re[s * 11], SCALEFACTOR32_1); + x05 = L_shr_pos(im[s * 11], SCALEFACTOR32_1); + x06 = L_shr_pos(re[s * 15], SCALEFACTOR32_1); + x07 = L_shr_pos(im[s * 15], SCALEFACTOR32_1); + x08 = L_shr_pos(re[s * 19], SCALEFACTOR32_1); + x09 = L_shr_pos(im[s * 19], SCALEFACTOR32_1); + x10 = L_shr_pos(re[s * 23], SCALEFACTOR32_1); + x11 = L_shr_pos(im[s * 23], SCALEFACTOR32_1); + x12 = L_shr_pos(re[s * 27], SCALEFACTOR32_1); + x13 = L_shr_pos(im[s * 27], SCALEFACTOR32_1); + x14 = L_shr_pos(re[s * 31], SCALEFACTOR32_1); + x15 = L_shr_pos(im[s * 31], SCALEFACTOR32_1); + + t00 = L_add(x00, x08); + t02 = L_sub(x00, x08); + t01 = L_add(x01, x09); + t03 = L_sub(x01, x09); + t04 = L_add(x02, x10); + t06 = L_sub(x02, x10); + t05 = L_add(x03, x11); + t07 = L_sub(x03, x11); + t08 = L_add(x04, x12); + t10 = L_sub(x04, x12); + t09 = L_add(x05, x13); + t11 = L_sub(x05, x13); + t12 = L_add(x06, x14); + t14 = L_sub(x06, x14); + t13 = L_add(x07, x15); + t15 = L_sub(x07, x15); + + /* Pre-additions and core multiplications */ + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + t01 = L_add(t06, t14); + t02 = L_sub(t06, t14); + t00 = L_add(t07, t15); + t03 = L_sub(t07, t15); + + Mpy3_0(s12, s13, s14, s15, t00, t01, t02, t03); + + /* Post-additions */ + y48 = L_add(s00, s02); + y56 = L_sub(s00, s02); + y49 = L_add(s01, s03); + y57 = L_sub(s01, s03); + y52 = L_sub(s04, s06); + y60 = L_add(s04, s06); + y53 = L_sub(s05, s07); + y61 = L_add(s05, s07); + y54 = L_add(s08, s14); + y62 = L_sub(s08, s14); + y55 = L_add(s09, s15); + y63 = L_sub(s09, s15); + y50 = L_add(s10, s12); + y58 = L_sub(s10, s12); + y51 = L_add(s11, s13); + y59 = L_sub(s11, s13); + + /* apply twiddle factors */ + y00 = L_shr_pos(y00, SCALEFACTOR32_2); + y01 = L_shr_pos(y01, SCALEFACTOR32_2); + y02 = L_shr_pos(y02, SCALEFACTOR32_2); + y03 = L_shr_pos(y03, SCALEFACTOR32_2); + y04 = L_shr_pos(y04, SCALEFACTOR32_2); + y05 = L_shr_pos(y05, SCALEFACTOR32_2); + y06 = L_shr_pos(y06, SCALEFACTOR32_2); + y07 = L_shr_pos(y07, SCALEFACTOR32_2); + y08 = L_shr_pos(y08, SCALEFACTOR32_2); + y09 = L_shr_pos(y09, SCALEFACTOR32_2); + y10 = L_shr_pos(y10, SCALEFACTOR32_2); + y11 = L_shr_pos(y11, SCALEFACTOR32_2); + y12 = L_shr_pos(y12, SCALEFACTOR32_2); + y13 = L_shr_pos(y13, SCALEFACTOR32_2); + y14 = L_shr_pos(y14, SCALEFACTOR32_2); + y15 = L_shr_pos(y15, SCALEFACTOR32_2); + y16 = L_shr_pos(y16, SCALEFACTOR32_2); + y17 = L_shr_pos(y17, SCALEFACTOR32_2); + y32 = L_shr_pos(y32, SCALEFACTOR32_2); + y33 = L_shr_pos(y33, SCALEFACTOR32_2); + y48 = L_shr_pos(y48, SCALEFACTOR32_2); + y49 = L_shr_pos(y49, SCALEFACTOR32_2); + y40 = L_shr_pos(y40, SCALEFACTOR32_2); + y41 = L_shr_pos(y41, SCALEFACTOR32_2); + + cplxMpy3_0(y18, y19, RotVector_32_32[2 * 0 + 0], RotVector_32_32[2 * 0 + 1]); + cplxMpy3_0(y20, y21, RotVector_32_32[2 * 1 + 0], RotVector_32_32[2 * 1 + 1]); + cplxMpy3_0(y22, y23, RotVector_32_32[2 * 2 + 0], RotVector_32_32[2 * 2 + 1]); + cplxMpy3_0(y24, y25, RotVector_32_32[2 * 3 + 0], RotVector_32_32[2 * 3 + 1]); + cplxMpy3_0(y26, y27, RotVector_32_32[2 * 4 + 0], RotVector_32_32[2 * 4 + 1]); + cplxMpy3_0(y28, y29, RotVector_32_32[2 * 5 + 0], RotVector_32_32[2 * 5 + 1]); + cplxMpy3_0(y30, y31, RotVector_32_32[2 * 6 + 0], RotVector_32_32[2 * 6 + 1]); + cplxMpy3_0(y34, y35, RotVector_32_32[2 * 7 + 0], RotVector_32_32[2 * 7 + 1]); + cplxMpy3_0(y36, y37, RotVector_32_32[2 * 8 + 0], RotVector_32_32[2 * 8 + 1]); + cplxMpy3_0(y38, y39, RotVector_32_32[2 * 9 + 0], RotVector_32_32[2 * 9 + 1]); + cplxMpy3_0(y42, y43, RotVector_32_32[2 * 10 + 0], RotVector_32_32[2 * 10 + 1]); + cplxMpy3_0(y44, y45, RotVector_32_32[2 * 11 + 0], RotVector_32_32[2 * 11 + 1]); + cplxMpy3_0(y46, y47, RotVector_32_32[2 * 12 + 0], RotVector_32_32[2 * 12 + 1]); + cplxMpy3_0(y50, y51, RotVector_32_32[2 * 13 + 0], RotVector_32_32[2 * 13 + 1]); + cplxMpy3_0(y52, y53, RotVector_32_32[2 * 14 + 0], RotVector_32_32[2 * 14 + 1]); + cplxMpy3_0(y54, y55, RotVector_32_32[2 * 15 + 0], RotVector_32_32[2 * 15 + 1]); + cplxMpy3_0(y56, y57, RotVector_32_32[2 * 16 + 0], RotVector_32_32[2 * 16 + 1]); + cplxMpy3_0(y58, y59, RotVector_32_32[2 * 17 + 0], RotVector_32_32[2 * 17 + 1]); + cplxMpy3_0(y60, y61, RotVector_32_32[2 * 18 + 0], RotVector_32_32[2 * 18 + 1]); + cplxMpy3_0(y62, y63, RotVector_32_32[2 * 19 + 0], RotVector_32_32[2 * 19 + 1]); + + /* 1. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y00, y32); + t02 = L_sub(y00, y32); + t01 = L_add(y01, y33); + t03 = L_sub(y01, y33); + t04 = L_add(y16, y48); + t07 = L_sub(y16, y48); + t05 = L_add(y49, y17); + t06 = L_sub(y49, y17); + + /* Post-additions */ + re[s * 0] = L_add(t00, t04); + move32(); + im[s * 0] = L_add(t01, t05); + move32(); + re[s * 8] = L_sub(t02, t06); + move32(); + im[s * 8] = L_sub(t03, t07); + move32(); + re[s * 16] = L_sub(t00, t04); + move32(); + im[s * 16] = L_sub(t01, t05); + move32(); + re[s * 24] = L_add(t02, t06); + move32(); + im[s * 24] = L_add(t03, t07); + move32(); + + /* 2. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y02, y34); + t02 = L_sub(y02, y34); + t01 = L_add(y03, y35); + t03 = L_sub(y03, y35); + t04 = L_add(y18, y50); + t07 = L_sub(y18, y50); + t05 = L_add(y51, y19); + t06 = L_sub(y51, y19); + + /* Post-additions */ + re[s * 1] = L_add(t00, t04); + move32(); + im[s * 1] = L_add(t01, t05); + move32(); + re[s * 9] = L_sub(t02, t06); + move32(); + im[s * 9] = L_sub(t03, t07); + move32(); + re[s * 17] = L_sub(t00, t04); + move32(); + im[s * 17] = L_sub(t01, t05); + move32(); + re[s * 25] = L_add(t02, t06); + move32(); + im[s * 25] = L_add(t03, t07); + move32(); + + /* 3. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y04, y36); + t02 = L_sub(y04, y36); + t01 = L_add(y05, y37); + t03 = L_sub(y05, y37); + t04 = L_add(y20, y52); + t07 = L_sub(y20, y52); + t05 = L_add(y53, y21); + t06 = L_sub(y53, y21); + + /* Post-additions */ + re[s * 2] = L_add(t00, t04); + move32(); + im[s * 2] = L_add(t01, t05); + move32(); + re[s * 10] = L_sub(t02, t06); + move32(); + im[s * 10] = L_sub(t03, t07); + move32(); + re[s * 18] = L_sub(t00, t04); + move32(); + im[s * 18] = L_sub(t01, t05); + move32(); + re[s * 26] = L_add(t02, t06); + move32(); + im[s * 26] = L_add(t03, t07); + move32(); + + /* 4. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y06, y38); + t02 = L_sub(y06, y38); + t01 = L_add(y07, y39); + t03 = L_sub(y07, y39); + t04 = L_add(y22, y54); + t07 = L_sub(y22, y54); + t05 = L_add(y55, y23); + t06 = L_sub(y55, y23); + + /* Post-additions */ + re[s * 3] = L_add(t00, t04); + move32(); + im[s * 3] = L_add(t01, t05); + move32(); + re[s * 11] = L_sub(t02, t06); + move32(); + im[s * 11] = L_sub(t03, t07); + move32(); + re[s * 19] = L_sub(t00, t04); + move32(); + im[s * 19] = L_sub(t01, t05); + move32(); + re[s * 27] = L_add(t02, t06); + move32(); + im[s * 27] = L_add(t03, t07); + move32(); + + /* 5. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y08, y41); + t02 = L_sub(y08, y41); + t01 = L_sub(y09, y40); + t03 = L_add(y09, y40); + t04 = L_add(y24, y56); + t07 = L_sub(y24, y56); + t05 = L_add(y57, y25); + t06 = L_sub(y57, y25); + + /* Post-additions */ + re[s * 4] = L_add(t00, t04); + move32(); + im[s * 4] = L_add(t01, t05); + move32(); + re[s * 12] = L_sub(t02, t06); + move32(); + im[s * 12] = L_sub(t03, t07); + move32(); + re[s * 20] = L_sub(t00, t04); + move32(); + im[s * 20] = L_sub(t01, t05); + move32(); + re[s * 28] = L_add(t02, t06); + move32(); + im[s * 28] = L_add(t03, t07); + move32(); + + /* 6. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y10, y42); + t02 = L_sub(y10, y42); + t01 = L_add(y11, y43); + t03 = L_sub(y11, y43); + t04 = L_add(y26, y58); + t07 = L_sub(y26, y58); + t05 = L_add(y59, y27); + t06 = L_sub(y59, y27); + + /* Post-additions */ + re[s * 5] = L_add(t00, t04); + move32(); + im[s * 5] = L_add(t01, t05); + move32(); + re[s * 13] = L_sub(t02, t06); + move32(); + im[s * 13] = L_sub(t03, t07); + move32(); + re[s * 21] = L_sub(t00, t04); + move32(); + im[s * 21] = L_sub(t01, t05); + move32(); + re[s * 29] = L_add(t02, t06); + move32(); + im[s * 29] = L_add(t03, t07); + move32(); + + /* 7. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y12, y44); + t02 = L_sub(y12, y44); + t01 = L_add(y13, y45); + t03 = L_sub(y13, y45); + t04 = L_add(y28, y60); + t07 = L_sub(y28, y60); + t05 = L_add(y61, y29); + t06 = L_sub(y61, y29); + + /* Post-additions */ + re[s * 6] = L_add(t00, t04); + move32(); + im[s * 6] = L_add(t01, t05); + move32(); + re[s * 14] = L_sub(t02, t06); + move32(); + im[s * 14] = L_sub(t03, t07); + move32(); + re[s * 22] = L_sub(t00, t04); + move32(); + im[s * 22] = L_sub(t01, t05); + move32(); + re[s * 30] = L_add(t02, t06); + move32(); + im[s * 30] = L_add(t03, t07); + move32(); + + /* 8. FFT4 stage */ + + /* Pre-additions */ + t00 = L_add(y14, y46); + t02 = L_sub(y14, y46); + t01 = L_add(y15, y47); + t03 = L_sub(y15, y47); + t04 = L_add(y30, y62); + t07 = L_sub(y30, y62); + t05 = L_add(y63, y31); + t06 = L_sub(y63, y31); + + /* Post-additions */ + re[s * 7] = L_add(t00, t04); + move32(); + im[s * 7] = L_add(t01, t05); + move32(); + re[s * 15] = L_sub(t02, t06); + move32(); + im[s * 15] = L_sub(t03, t07); + move32(); + re[s * 23] = L_sub(t00, t04); + move32(); + im[s * 23] = L_sub(t01, t05); + move32(); + re[s * 31] = L_add(t02, t06); + move32(); + im[s * 31] = L_add(t03, t07); + move32(); + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Function performs a complex 40-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR40 bits. + * + * \param [i/o] re real part + * \param [i/o] im imag part + * \param [i ] sx stride real and imag part + * + * \return void + */ + + + +static void fft40(Word32 *re, Word32 *im, Word16 sx, Word32 *x) +{ + Dyn_Mem_Deluxe_In(const Word32 *W; Word16 dim1, dim2; Counter i, j; + Word32 x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15; + Word32 t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15; + Word32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09, s10, s11, s12, s13, s14, s15;); + + dim1 = 5; + move16(); + dim2 = 8; + move16(); + + W = RotVector_40_32; + + FOR (i = 0; i < dim2; i++) + { + FOR (j = 0; j < dim1; j++) + { + x[2 * i * dim1 + 2 * j] = re[sx * i + sx * j * dim2]; + move32(); + x[2 * i * dim1 + 2 * j + 1] = im[sx * i + sx * j * dim2]; + move32(); + } + } + + FOR (i = 0; i < dim2; i++) + { + fft5(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + + FOR (i = 0; i < dim1; i++) + { + cplxMpy4_8_1(x00, x01, x[2 * i + 2 * 0 * dim1], x[2 * i + 2 * 0 * dim1 + 1]); + + IF (i == 0) + { + cplxMpy4_8_1(x02, x03, x[2 * i + 2 * 1 * dim1], x[2 * i + 2 * 1 * dim1 + 1]); + cplxMpy4_8_1(x04, x05, x[2 * i + 2 * 2 * dim1], x[2 * i + 2 * 2 * dim1 + 1]); + cplxMpy4_8_1(x06, x07, x[2 * i + 2 * 3 * dim1], x[2 * i + 2 * 3 * dim1 + 1]); + cplxMpy4_8_1(x08, x09, x[2 * i + 2 * 4 * dim1], x[2 * i + 2 * 4 * dim1 + 1]); + cplxMpy4_8_1(x10, x11, x[2 * i + 2 * 5 * dim1], x[2 * i + 2 * 5 * dim1 + 1]); + cplxMpy4_8_1(x12, x13, x[2 * i + 2 * 6 * dim1], x[2 * i + 2 * 6 * dim1 + 1]); + cplxMpy4_8_1(x14, x15, x[2 * i + 2 * 7 * dim1], x[2 * i + 2 * 7 * dim1 + 1]); + } + ELSE + { + cplxMpy4_8_2(x02, x03, x[2 * i + 2 * 1 * dim1], x[2 * i + 2 * 1 * dim1 + 1], W[2 * (i - 1) + 0 * 2 * 4], + W[2 * (i - 1) + 0 * 2 * 4 + 1]); + cplxMpy4_8_2(x04, x05, x[2 * i + 2 * 2 * dim1], x[2 * i + 2 * 2 * dim1 + 1], W[2 * (i - 1) + 1 * 2 * 4], + W[2 * (i - 1) + 1 * 2 * 4 + 1]); + cplxMpy4_8_2(x06, x07, x[2 * i + 2 * 3 * dim1], x[2 * i + 2 * 3 * dim1 + 1], W[2 * (i - 1) + 2 * 2 * 4], + W[2 * (i - 1) + 2 * 2 * 4 + 1]); + cplxMpy4_8_2(x08, x09, x[2 * i + 2 * 4 * dim1], x[2 * i + 2 * 4 * dim1 + 1], W[2 * (i - 1) + 3 * 2 * 4], + W[2 * (i - 1) + 3 * 2 * 4 + 1]); + cplxMpy4_8_2(x10, x11, x[2 * i + 2 * 5 * dim1], x[2 * i + 2 * 5 * dim1 + 1], W[2 * (i - 1) + 4 * 2 * 4], + W[2 * (i - 1) + 4 * 2 * 4 + 1]); + cplxMpy4_8_2(x12, x13, x[2 * i + 2 * 6 * dim1], x[2 * i + 2 * 6 * dim1 + 1], W[2 * (i - 1) + 5 * 2 * 4], + W[2 * (i - 1) + 5 * 2 * 4 + 1]); + cplxMpy4_8_2(x14, x15, x[2 * i + 2 * 7 * dim1], x[2 * i + 2 * 7 * dim1 + 1], W[2 * (i - 1) + 6 * 2 * 4], + W[2 * (i - 1) + 6 * 2 * 4 + 1]); + } + + t00 = L_shr_pos(L_add(x00, x08), SCALEFACTORN2 - 1); + t02 = L_shr_pos(L_sub(x00, x08), SCALEFACTORN2 - 1); + t01 = L_shr_pos(L_add(x01, x09), SCALEFACTORN2 - 1); + t03 = L_shr_pos(L_sub(x01, x09), SCALEFACTORN2 - 1); + t04 = L_shr_pos(L_add(x02, x10), SCALEFACTORN2 - 1); + t06 = L_sub(x02, x10); + t05 = L_shr_pos(L_add(x03, x11), SCALEFACTORN2 - 1); + t07 = L_sub(x03, x11); + t08 = L_shr_pos(L_add(x04, x12), SCALEFACTORN2 - 1); + t10 = L_shr_pos(L_sub(x04, x12), SCALEFACTORN2 - 1); + t09 = L_shr_pos(L_add(x05, x13), SCALEFACTORN2 - 1); + t11 = L_shr_pos(L_sub(x05, x13), SCALEFACTORN2 - 1); + t12 = L_shr_pos(L_add(x06, x14), SCALEFACTORN2 - 1); + t14 = L_sub(x06, x14); + t13 = L_shr_pos(L_add(x07, x15), SCALEFACTORN2 - 1); + t15 = L_sub(x07, x15); + + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + + t01 = L_shr_pos(L_add(t06, t14), SCALEFACTORN2 - 1); + t02 = L_shr_pos(L_sub(t06, t14), SCALEFACTORN2 - 1); + t00 = L_shr_pos(L_add(t07, t15), SCALEFACTORN2 - 1); + t03 = L_shr_pos(L_sub(t07, t15), SCALEFACTORN2 - 1); + + s12 = Mpy_32_32_lc3plus(L_add(t00, t02), C81_32); + s14 = Mpy_32_32_lc3plus(L_sub(t00, t02), C81_32); + s13 = Mpy_32_32_lc3plus(L_sub(t03, t01), C81_32); + s15 = Mpy_32_32_lc3plus(L_add(t01, t03), C82_32); + + re[sx * i + sx * 0 * dim1] = L_add(s00, s02); + move32(); + im[sx * i + sx * 0 * dim1] = L_add(s01, s03); + move32(); + re[sx * i + sx * 1 * dim1] = L_add(s10, s12); + move32(); + im[sx * i + sx * 1 * dim1] = L_add(s11, s13); + move32(); + re[sx * i + sx * 2 * dim1] = L_sub(s04, s06); + move32(); + im[sx * i + sx * 2 * dim1] = L_sub(s05, s07); + move32(); + re[sx * i + sx * 3 * dim1] = L_add(s08, s14); + move32(); + im[sx * i + sx * 3 * dim1] = L_add(s09, s15); + move32(); + re[sx * i + sx * 4 * dim1] = L_sub(s00, s02); + move32(); + im[sx * i + sx * 4 * dim1] = L_sub(s01, s03); + move32(); + re[sx * i + sx * 5 * dim1] = L_sub(s10, s12); + move32(); + im[sx * i + sx * 5 * dim1] = L_sub(s11, s13); + move32(); + re[sx * i + sx * 6 * dim1] = L_add(s04, s06); + move32(); + im[sx * i + sx * 6 * dim1] = L_add(s05, s07); + move32(); + re[sx * i + sx * 7 * dim1] = L_sub(s08, s14); + move32(); + im[sx * i + sx * 7 * dim1] = L_sub(s09, s15); + move32(); + } + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Combined FFT + * + * \param [i/o] re real part + * \param [i/o] im imag part + * \param [i ] W rotation factor + * \param [i ] dim1 length of fft1 + * \param [i ] dim2 length of fft2 + * \param [i ] sx stride real and imag part + * \param [i ] sc stride phase rotation coefficients + * \param [tmp] x 32-bit workbuffer of length=2*len + * \param [i ] Woff offset for addressing the rotation vector table + * + * \return void + */ + + +static void fftN2(Word32 *re, Word32 *im, +#ifdef ENABLE_HR_MODE + const Word32 *W, +#else + const Word16 *W, +#endif + Word16 dim1, Word16 dim2, Word16 sx, Word16 sc, + Word16 Woff + , Word8 *scratchBuffer +#ifdef ENABLE_FFT_RESCALE + , Word16 *scale +#endif + ) +{ + Dyn_Mem_Deluxe_In(Counter i, j;); + + Word32 *x = scratchAlign(scratchBuffer, 0); + + FOR (i = 0; i < dim2; i++) + { + FOR (j = 0; j < dim1; j++) + { + x[2 * i * dim1 + 2 * j] = re[sx * i + sx * j * dim2]; + move32(); + x[2 * i * dim1 + 2 * j + 1] = im[sx * i + sx * j * dim2]; + move32(); + } + } + + SWITCH (dim1) + { + + case 4: + FOR (i = 0; i < dim2; i++) + { + fft4(&x[i * 2 * dim1]); + } + BREAK; + case 8: + FOR (i = 0; i < dim2; i++) + { + fft8(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + BREAK; + + case 10: + FOR (i = 0; i < dim2; i++) + { + fft10(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + BREAK; + case 15: + FOR (i = 0; i < dim2; i++) + { + fft15(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + + BREAK; + case 16: + FOR (i = 0; i < dim2; i++) + { + fft16(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + BREAK; + case 20: + FOR (i = 0; i < dim2; i++) + { + fft20(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + BREAK; + case 30: + FOR (i = 0; i < dim2; i++) + { + fft30(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + BREAK; + case 32: + FOR (i = 0; i < dim2; i++) + { + fft32(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); + } + BREAK; +#ifdef ENABLE_HR_MODE +#if (defined LC3_FFT15) + case 60: + FOR (i = 0; i < dim2; i++) + { +#ifndef ENABLE_FFT_RESCALE + fftN2(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], RotVector_480, 15, 4, sx, 4, 60, scratch); +#else + fftN2(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], RotVector_480, 15, 4, sx, 4, 60, scratch, NULL); +#endif + } + BREAK; +#endif +#endif + default: ASSERT(0); + } + +#ifdef ENABLE_FFT_RESCALE + IF (scale) + { + *scale = s_max(sub(getScaleFactor32_lc3plus(x, dim1 * dim2 * 2), FFT_RESCALE_HR), 0); move16(); + +#if defined(FUNCTION_scaleValues_32) + scaleValues_32(x, dim1 * dim2, *scale); +#else + FOR (i = 0; i < dim1 * dim2 * 2; i++) + { + x[i] = L_shl_pos(x[i], *scale); move32(); + } + } +#endif +#endif + + SWITCH (dim2) + { + case 4: + { + Word32 x00, x01, x02, x03, x04, x05, x06, x07; + Word32 t00, t01, t02, t03, t04, t05, t06, t07; + + j = add(8, 0); + FOR (i = 0; i < dim1; i++) + { + cplxMpy4_4_1(x00, x01, x[2 * i + 2 * 0 * dim1], x[2 * i + 2 * 0 * dim1 + 1]); + IF (i == 0) + { + cplxMpy4_4_1(x02, x03, x[2 * i + 2 * 1 * dim1], x[2 * i + 2 * 1 * dim1 + 1]); + cplxMpy4_4_1(x04, x05, x[2 * i + 2 * 2 * dim1], x[2 * i + 2 * 2 * dim1 + 1]); + cplxMpy4_4_1(x06, x07, x[2 * i + 2 * 3 * dim1], x[2 * i + 2 * 3 * dim1 + 1]); + } + ELSE + { + cplxMpy4_4_0(x02, x03, x[2 * i + 2 * 1 * dim1], x[2 * i + 2 * 1 * dim1 + 1], + W[sc * i + j * 1 * dim1 - Woff], W[sc * i + j * 1 * dim1 + 1 - Woff]); + cplxMpy4_4_0(x04, x05, x[2 * i + 2 * 2 * dim1], x[2 * i + 2 * 2 * dim1 + 1], + W[sc * i + j * 2 * dim1 - Woff], W[sc * i + j * 2 * dim1 + 1 - Woff]); + cplxMpy4_4_0(x06, x07, x[2 * i + 2 * 3 * dim1], x[2 * i + 2 * 3 * dim1 + 1], + W[sc * i + j * 3 * dim1 - Woff], W[sc * i + j * 3 * dim1 + 1 - Woff]); + } + + t00 = L_add(x00, x04); + t02 = L_sub(x00, x04); + t01 = L_add(x01, x05); + t03 = L_sub(x01, x05); + t04 = L_add(x02, x06); + t07 = L_sub(x02, x06); + t05 = L_add(x07, x03); + t06 = L_sub(x07, x03); + + re[sx * i + sx * 0 * dim1] = L_add(t00, t04); + move32(); + im[sx * i + sx * 0 * dim1] = L_add(t01, t05); + move32(); + re[sx * i + sx * 1 * dim1] = L_sub(t02, t06); + move32(); + im[sx * i + sx * 1 * dim1] = L_sub(t03, t07); + move32(); + re[sx * i + sx * 2 * dim1] = L_sub(t00, t04); + move32(); + im[sx * i + sx * 2 * dim1] = L_sub(t01, t05); + move32(); + re[sx * i + sx * 3 * dim1] = L_add(t02, t06); + move32(); + im[sx * i + sx * 3 * dim1] = L_add(t03, t07); + move32(); + } + + BREAK; + } + +#ifdef CR8_G_ADD_75MS + case 6: + { + Word32 y[2 * 10]; + FOR (j = 0; j < dim2; j++) + { + cplxMpy4_12_1(y[2 * j], y[2 * j + 1], x[2 * 0 + 2 * j * dim1], x[2 * 0 + 2 * j * dim1 + 1]); + } + fft6(&y[0], &y[1], 2); + FOR (j = 0; j < dim2; j++) + { + re[sx * 0 + sx * j * dim1] = y[2 * j]; + move32(); + im[sx * 0 + sx * j * dim1] = y[2 * j + 1]; + move32(); + } + + FOR (i = 1; i < dim1; i++) + { + cplxMpy4_12_1(y[2 * (0 + 0)], y[2 * (0 + 0) + 1], x[2 * i + 2 * (0 + 0) * dim1], + x[2 * i + 2 * (0 + 0) * dim1 + 1]); + cplxMpy4_12_0(y[2 * (0 + 1)], y[2 * (0 + 1) + 1], x[2 * i + 2 * (0 + 1) * dim1], + x[2 * i + 2 * (0 + 1) * dim1 + 1], W[sc * i + sc * (0 + 1) * dim1 - Woff], + W[sc * i + sc * (0 + 1) * dim1 + 1 - Woff]); + FOR (j = 2; j < dim2; j = j + 2) + { + cplxMpy4_12_0(y[2 * (j + 0)], y[2 * (j + 0) + 1], x[2 * i + 2 * (j + 0) * dim1], + x[2 * i + 2 * (j + 0) * dim1 + 1], W[sc * i + sc * (j + 0) * dim1 - Woff], + W[sc * i + sc * (j + 0) * dim1 + 1 - Woff]); + cplxMpy4_12_0(y[2 * (j + 1)], y[2 * (j + 1) + 1], x[2 * i + 2 * (j + 1) * dim1], + x[2 * i + 2 * (j + 1) * dim1 + 1], W[sc * i + sc * (j + 1) * dim1 - Woff], + W[sc * i + sc * (j + 1) * dim1 + 1 - Woff]); + } + fft6(&y[0], &y[1], 2); + FOR (j = 0; j < dim2; j++) + { + re[sx * i + sx * j * dim1] = y[2 * j]; + move32(); + im[sx * i + sx * j * dim1] = y[2 * j + 1]; + move32(); + } + } + BREAK; + } +#endif + + case 8: + { + Word32 x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15; + Word32 t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15; + Word32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09, s10, s11, s12, s13, s14, s15; + + FOR (i = 0; i < dim1; i++) + { + cplxMpy4_8_1(x00, x01, x[2 * i + 2 * 0 * dim1], x[2 * i + 2 * 0 * dim1 + 1]); + IF (i == 0) + { + cplxMpy4_8_1(x02, x03, x[2 * i + 2 * 1 * dim1], x[2 * i + 2 * 1 * dim1 + 1]); + cplxMpy4_8_1(x04, x05, x[2 * i + 2 * 2 * dim1], x[2 * i + 2 * 2 * dim1 + 1]); + cplxMpy4_8_1(x06, x07, x[2 * i + 2 * 3 * dim1], x[2 * i + 2 * 3 * dim1 + 1]); + cplxMpy4_8_1(x08, x09, x[2 * i + 2 * 4 * dim1], x[2 * i + 2 * 4 * dim1 + 1]); + cplxMpy4_8_1(x10, x11, x[2 * i + 2 * 5 * dim1], x[2 * i + 2 * 5 * dim1 + 1]); + cplxMpy4_8_1(x12, x13, x[2 * i + 2 * 6 * dim1], x[2 * i + 2 * 6 * dim1 + 1]); + cplxMpy4_8_1(x14, x15, x[2 * i + 2 * 7 * dim1], x[2 * i + 2 * 7 * dim1 + 1]); + } + ELSE + { + cplxMpy4_8_0(x02, x03, x[2 * i + 2 * 1 * dim1], x[2 * i + 2 * 1 * dim1 + 1], + W[sc * i + sc * 1 * dim1 - Woff], W[sc * i + sc * 1 * dim1 + 1 - Woff]); + cplxMpy4_8_0(x04, x05, x[2 * i + 2 * 2 * dim1], x[2 * i + 2 * 2 * dim1 + 1], + W[sc * i + sc * 2 * dim1 - Woff], W[sc * i + sc * 2 * dim1 + 1 - Woff]); + cplxMpy4_8_0(x06, x07, x[2 * i + 2 * 3 * dim1], x[2 * i + 2 * 3 * dim1 + 1], + W[sc * i + sc * 3 * dim1 - Woff], W[sc * i + sc * 3 * dim1 + 1 - Woff]); + cplxMpy4_8_0(x08, x09, x[2 * i + 2 * 4 * dim1], x[2 * i + 2 * 4 * dim1 + 1], + W[sc * i + sc * 4 * dim1 - Woff], W[sc * i + sc * 4 * dim1 + 1 - Woff]); + cplxMpy4_8_0(x10, x11, x[2 * i + 2 * 5 * dim1], x[2 * i + 2 * 5 * dim1 + 1], + W[sc * i + sc * 5 * dim1 - Woff], W[sc * i + sc * 5 * dim1 + 1 - Woff]); + cplxMpy4_8_0(x12, x13, x[2 * i + 2 * 6 * dim1], x[2 * i + 2 * 6 * dim1 + 1], + W[sc * i + sc * 6 * dim1 - Woff], W[sc * i + sc * 6 * dim1 + 1 - Woff]); + cplxMpy4_8_0(x14, x15, x[2 * i + 2 * 7 * dim1], x[2 * i + 2 * 7 * dim1 + 1], + W[sc * i + sc * 7 * dim1 - Woff], W[sc * i + sc * 7 * dim1 + 1 - Woff]); + } + + t00 = L_shr_pos(L_add(x00, x08), SCALEFACTORN2 - 1); + t02 = L_shr_pos(L_sub(x00, x08), SCALEFACTORN2 - 1); + t01 = L_shr_pos(L_add(x01, x09), SCALEFACTORN2 - 1); + t03 = L_shr_pos(L_sub(x01, x09), SCALEFACTORN2 - 1); + t04 = L_shr_pos(L_add(x02, x10), SCALEFACTORN2 - 1); + t06 = L_sub(x02, x10); + t05 = L_shr_pos(L_add(x03, x11), SCALEFACTORN2 - 1); + t07 = L_sub(x03, x11); + t08 = L_shr_pos(L_add(x04, x12), SCALEFACTORN2 - 1); + t10 = L_shr_pos(L_sub(x04, x12), SCALEFACTORN2 - 1); + t09 = L_shr_pos(L_add(x05, x13), SCALEFACTORN2 - 1); + t11 = L_shr_pos(L_sub(x05, x13), SCALEFACTORN2 - 1); + t12 = L_shr_pos(L_add(x06, x14), SCALEFACTORN2 - 1); + t14 = L_sub(x06, x14); + t13 = L_shr_pos(L_add(x07, x15), SCALEFACTORN2 - 1); + t15 = L_sub(x07, x15); + + s00 = L_add(t00, t08); + s04 = L_sub(t00, t08); + s01 = L_add(t01, t09); + s05 = L_sub(t01, t09); + s08 = L_sub(t02, t11); + s10 = L_add(t02, t11); + s09 = L_add(t03, t10); + s11 = L_sub(t03, t10); + s02 = L_add(t04, t12); + s07 = L_sub(t04, t12); + s03 = L_add(t05, t13); + s06 = L_sub(t13, t05); + + t01 = L_shr_pos(L_add(t06, t14), SCALEFACTORN2 - 1); + t02 = L_shr_pos(L_sub(t06, t14), SCALEFACTORN2 - 1); + t00 = L_shr_pos(L_add(t07, t15), SCALEFACTORN2 - 1); + t03 = L_shr_pos(L_sub(t07, t15), SCALEFACTORN2 - 1); + + s12 = Mpy_32_xx(L_add(t00, t02), C81); + s14 = Mpy_32_xx(L_sub(t00, t02), C81); + s13 = Mpy_32_xx(L_sub(t03, t01), C81); + s15 = Mpy_32_xx(L_add(t01, t03), C82); + + re[sx * i + sx * 0 * dim1] = L_add(s00, s02); + move32(); + im[sx * i + sx * 0 * dim1] = L_add(s01, s03); + move32(); + re[sx * i + sx * 1 * dim1] = L_add(s10, s12); + move32(); + im[sx * i + sx * 1 * dim1] = L_add(s11, s13); + move32(); + re[sx * i + sx * 2 * dim1] = L_sub(s04, s06); + move32(); + im[sx * i + sx * 2 * dim1] = L_sub(s05, s07); + move32(); + re[sx * i + sx * 3 * dim1] = L_add(s08, s14); + move32(); + im[sx * i + sx * 3 * dim1] = L_add(s09, s15); + move32(); + re[sx * i + sx * 4 * dim1] = L_sub(s00, s02); + move32(); + im[sx * i + sx * 4 * dim1] = L_sub(s01, s03); + move32(); + re[sx * i + sx * 5 * dim1] = L_sub(s10, s12); + move32(); + im[sx * i + sx * 5 * dim1] = L_sub(s11, s13); + move32(); + re[sx * i + sx * 6 * dim1] = L_add(s04, s06); + move32(); + im[sx * i + sx * 6 * dim1] = L_add(s05, s07); + move32(); + re[sx * i + sx * 7 * dim1] = L_sub(s08, s14); + move32(); + im[sx * i + sx * 7 * dim1] = L_sub(s09, s15); + move32(); + } + BREAK; + } + + case 12: + { + Word32 y[2 * 20]; + FOR (j = 0; j < dim2; j++) + { + cplxMpy4_12_1(y[2 * j], y[2 * j + 1], x[2 * 0 + 2 * j * dim1], x[2 * 0 + 2 * j * dim1 + 1]); + } + fft12(y); + FOR (j = 0; j < dim2; j++) + { + re[sx * 0 + sx * j * dim1] = y[2 * j]; + move32(); + im[sx * 0 + sx * j * dim1] = y[2 * j + 1]; + move32(); + } + + FOR (i = 1; i < dim1; i++) + { + cplxMpy4_12_1(y[2 * (0 + 0)], y[2 * (0 + 0) + 1], x[2 * i + 2 * (0 + 0) * dim1], + x[2 * i + 2 * (0 + 0) * dim1 + 1]); + cplxMpy4_12_0(y[2 * (0 + 1)], y[2 * (0 + 1) + 1], x[2 * i + 2 * (0 + 1) * dim1], + x[2 * i + 2 * (0 + 1) * dim1 + 1], W[sc * i + sc * (0 + 1) * dim1 - Woff], + W[sc * i + sc * (0 + 1) * dim1 + 1 - Woff]); + FOR (j = 2; j < dim2; j = j + 2) + { + cplxMpy4_12_0(y[2 * (j + 0)], y[2 * (j + 0) + 1], x[2 * i + 2 * (j + 0) * dim1], + x[2 * i + 2 * (j + 0) * dim1 + 1], W[sc * i + sc * (j + 0) * dim1 - Woff], + W[sc * i + sc * (j + 0) * dim1 + 1 - Woff]); + cplxMpy4_12_0(y[2 * (j + 1)], y[2 * (j + 1) + 1], x[2 * i + 2 * (j + 1) * dim1], + x[2 * i + 2 * (j + 1) * dim1 + 1], W[sc * i + sc * (j + 1) * dim1 - Woff], + W[sc * i + sc * (j + 1) * dim1 + 1 - Woff]); + } + fft12(y); + FOR (j = 0; j < dim2; j++) + { + re[sx * i + sx * j * dim1] = y[2 * j]; + move32(); + im[sx * i + sx * j * dim1] = y[2 * j + 1]; + move32(); + } + } + BREAK; + } + +#if defined(ENABLE_HR_MODE) + case 16: + { + Word32 y[2 * 20]; + FOR (j = 0; j < dim2; j++) + { + cplxMpy4_16_1(y[2 * j], y[2 * j + 1], x[2 * 0 + 2 * j * dim1], x[2 * 0 + 2 * j * dim1 + 1]); + } + + fft16(&y[0], &y[1], 2); + FOR (j = 0; j < dim2; j++) + { + re[sx * 0 + sx * j * dim1] = y[2 * j]; + move32(); + im[sx * 0 + sx * j * dim1] = y[2 * j + 1]; + move32(); + } + + FOR (i = 1; i < dim1; i++) + { + cplxMpy4_16_1(y[2 * (0 + 0)], y[2 * (0 + 0) + 1], x[2 * i + 2 * (0 + 0) * dim1], + x[2 * i + 2 * (0 + 0) * dim1 + 1]); + cplxMpy4_16_0(y[2 * (0 + 1)], y[2 * (0 + 1) + 1], x[2 * i + 2 * (0 + 1) * dim1], + x[2 * i + 2 * (0 + 1) * dim1 + 1], W[sc * i + sc * (0 + 1) * dim1 - Woff], + W[sc * i + sc * (0 + 1) * dim1 + 1 - Woff]); + FOR (j = 2; j < dim2; j = j + 2) + { + cplxMpy4_16_0(y[2 * (j + 0)], y[2 * (j + 0) + 1], x[2 * i + 2 * (j + 0) * dim1], + x[2 * i + 2 * (j + 0) * dim1 + 1], W[sc * i + sc * (j + 0) * dim1 - Woff], + W[sc * i + sc * (j + 0) * dim1 + 1 - Woff]); + cplxMpy4_16_0(y[2 * (j + 1)], y[2 * (j + 1) + 1], x[2 * i + 2 * (j + 1) * dim1], + x[2 * i + 2 * (j + 1) * dim1 + 1], W[sc * i + sc * (j + 1) * dim1 - Woff], + W[sc * i + sc * (j + 1) * dim1 + 1 - Woff]); + } + fft16(&y[0], &y[1], 2); + FOR (j = 0; j < dim2; j++) + { + re[sx * i + sx * j * dim1] = y[2 * j]; + move32(); + im[sx * i + sx * j * dim1] = y[2 * j + 1]; + move32(); + } + } + BREAK; + } +# endif + default: ASSERT(0); + } + + Dyn_Mem_Deluxe_Out(); +} + +/** + * \brief Complex valued FFT + * + * \param [i/o] re real part + * \param [i/o] im imag part + * \param [i ] sizeOfFft length of fft + * \param [i ] s stride real and imag part + * \param [i ] scale scalefactor + * + * \return void + */ + + + +/* x is the scratch buffer */ +void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 length, Word16 s, Word16 *scale, Word32 *x) +{ +#if (defined ENABLE_FFT_RESCALE) && ((defined LC3_FFT30) || (defined ENABLE_HR_MODE)) + Word16 fftN2scale = 0; +#endif + +#ifdef ENABLE_HR_MODE + Word8 scratch[6128] = {0}; +#else + Word8 scratch[4068] = {0}; +#endif + + SWITCH (length) + { + + case 10: + fft10(re, im, s); + *scale = add(*scale, SCALEFACTOR10); + move16(); + BREAK; + case 16: + fft16(re, im, s); + *scale = add(*scale, SCALEFACTOR16); + move16(); + BREAK; + case 20: + fft20(re, im, s); + *scale = add(*scale, SCALEFACTOR20); + move16(); + BREAK; + case 30: + fft30(re, im, s); + *scale = add(*scale, SCALEFACTOR30); + move16(); + BREAK; + case 32: + fft32(re, im, s); + *scale = add(*scale, SCALEFACTOR32); + move16(); + BREAK; + case 40: + fft40(re, im, s, x); + *scale = add(*scale, SCALEFACTOR40); + move16(); + BREAK; + case 48: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_32_12, 4, 12, s, 16, 64, scratch); +#else + fftN2(re, im, RotVector_32_12, 4, 12, s, 16, 64, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR48); + move16(); + BREAK; + case 60: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_480, 15, 4, s, 4, 60, scratch); +#else + fftN2(re, im, RotVector_480, 15, 4, s, 4, 60, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR60); + move16(); + BREAK; + case 64: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_32_8, 8, 8, s, 8, 64, scratch); +#else + fftN2(re, im, RotVector_32_8, 8, 8, s, 8, 64, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR64); + move16(); + BREAK; + case 80: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_320, 10, 8, s, 4, 40, scratch); +#else + fftN2(re, im, RotVector_320, 10, 8, s, 4, 40, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR80); + move16(); + BREAK; + case 90: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_15_6, 15, 6, s, 2, 30, scratch); +#else + fftN2(re, im, RotVector_15_6, 15, 6, s, 2, 30, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR90); + move16(); + BREAK; + + case 120: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_480, 15, 8, s, 4, 60, scratch); +#else + fftN2(re, im, RotVector_480, 15, 8, s, 4, 60, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR120); + move16(); + BREAK; + case 128: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_32_8, 16, 8, s, 4, 64, scratch); +#else + fftN2(re, im, RotVector_32_8, 16, 8, s, 4, 64, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR128); + move16(); + BREAK; + case 160: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_320, 20, 8, s, 2, 40, scratch); +#else + fftN2(re, im, RotVector_320, 20, 8, s, 2, 40, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR160); + move16(); + BREAK; + case 180: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_360, 15, 12, s, 4, 60, scratch); + *scale = add(*scale, SCALEFACTOR180); +#else + fftN2(re, im, RotVector_360, 15, 12, s, 4, 60, scratch, &fftN2scale); + *scale = add(*scale, SCALEFACTOR180); + *scale = sub(*scale, fftN2scale); move16(); +#endif + + move16(); + BREAK; + case 192: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_32_12, 16, 12, s, 4, 64, scratch); +#else + fftN2(re, im, RotVector_32_12, 16, 12, s, 4, 64, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR192); + move16(); + BREAK; + case 240: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_480, 30, 8, s, 2, 60, scratch); + *scale = add(*scale, SCALEFACTOR240); +#else + fftN2(re, im, RotVector_480, 30, 8, s, 2, 60, scratch, &fftN2scale); + *scale = add(*scale, SCALEFACTOR240); + *scale = sub(*scale, fftN2scale); move16(); +#endif + move16(); + BREAK; + case 256: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_32_8, 32, 8, s, 2, 64, scratch); +#else + fftN2(re, im, RotVector_32_8, 32, 8, s, 2, 64, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR256); + move16(); + BREAK; + case 384: +#ifndef ENABLE_FFT_RESCALE + fftN2(re, im, RotVector_32_12, 32, 12, s, 2, 64, scratch); +#else + fftN2(re, im, RotVector_32_12, 32, 12, s, 2, 64, scratch, NULL); +#endif + *scale = add(*scale, SCALEFACTOR384); + move16(); + BREAK; +#ifdef ENABLE_HR_MODE +#ifdef CR8_G_ADD_75MS + case 360: + fftN2(re, im, RotVector_720, 30, 12, s, 2, 60, scratch, &fftN2scale); + *scale = add(*scale, SCALEFACTOR360); move16(); + *scale = sub(*scale, fftN2scale); move16(); + BREAK; +#endif + case 480: +#ifndef ENABLE_FFT_RESCALE +#ifndef ENABLE_FFT_30X16 + fftN2(re, im, RotVector_960, 60, 8, s, 2, 120, scratch); +#else + fftN2(re, im, RotVector_30_16, 30, 16, s, 2, 60, scratch); +#endif + *scale = add(*scale, SCALEFACTOR480); move16(); +#else +#ifndef ENABLE_FFT_30X16 + fftN2(re, im, RotVector_960, 60, 8, s, 2, 120, scratch, &fftN2scale); +#else + fftN2(re, im, RotVector_30_16, 30, 16, s, 2, 60, scratch, &fftN2scale); +#endif + *scale = add(*scale, SCALEFACTOR480); move16(); + *scale = sub(*scale, fftN2scale); move16(); +#endif + BREAK; +#endif + default: ASSERT(0); + } +} + + +#define RFFT_TWIDDLE1(x, t1, t2, t3, t4, w1, w2, xb0, xb1, xt0, xt1) \ + do \ + { \ + xb0 = L_shr_pos(x[2 * i + 0], 2); \ + xb1 = L_shr_pos(x[2 * i + 1], 2); \ + xt0 = L_shr_pos(x[sizeOfFft - 2 * i + 0], 2); \ + xt1 = L_shr_pos(x[sizeOfFft - 2 * i + 1], 2); \ + t1 = L_sub(xb0, xt0); \ + t2 = L_add(xb1, xt1); \ + t3 = L_sub(Mpy_32_32_lc3plus(t1, w1), Mpy_32_32_lc3plus(t2, w2)); \ + t4 = L_add(Mpy_32_32_lc3plus(t1, w2), Mpy_32_32_lc3plus(t2, w1)); \ + t1 = L_add(xb0, xt0); \ + t2 = L_sub(xb1, xt1); \ + } while (0) + +#define RFFT_TWIDDLE2(x, t1, t2, t3, t4, w1, w2, xb0, xb1, xt0, xt1) \ + do \ + { \ + xb0 = L_shr_pos(x[2 * i + 0], 2); \ + xb1 = L_shr_pos(x[2 * i + 1], 2); \ + xt0 = L_shr_pos(x[sizeOfFft - 2 * i + 0], 2); \ + xt1 = L_shr_pos(x[sizeOfFft - 2 * i + 1], 2); \ + t1 = L_sub(xb0, xt0); \ + t2 = L_add(xb1, xt1); \ + t3 = L_add(Mpy_32_32_lc3plus(t1, w1), Mpy_32_32_lc3plus(t2, w2)); \ + t4 = L_sub(Mpy_32_32_lc3plus(t2, w1), Mpy_32_32_lc3plus(t1, w2)); \ + t1 = L_add(xb0, xt0); \ + t2 = L_sub(xb1, xt1); \ + } while (0) + + + +static const Word32 *rfft_twid(int size) +{ + SWITCH (size) + { + case 32: return RealFFT32_twid; + case 40: return RealFFT40_twid; + case 64: return RealFFT64_twid; + case 80: return RealFFT80_twid; + case 96: return RealFFT96_twid; + case 128: return RealFFT128_twid; + case 192: return RealFFT192_twid; + case 256: return RealFFT256_twid; + case 384: return RealFFT384_twid; + case 512: return RealFFT512_twid; + case 768: return RealFFT768_twid; + default: ASSERT(0); + } + return NULL; +} + + +void BASOP_rfftN(Word32 *x, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer) +{ + Dyn_Mem_Deluxe_In(Counter i; Word16 sizeOfFft2, sizeOfFft4, sizeOfFft8; Word32 t1, t2, t3, t4, xb0, xb1, xt0, xt1; + Word32 * workBuffer; const Word32 *w32;); + + workBuffer = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * sizeOfFft */ + w32 = rfft_twid(sizeOfFft); + + sizeOfFft2 = shr_pos(sizeOfFft, 1); + sizeOfFft4 = shr_pos(sizeOfFft, 2); + sizeOfFft8 = shr_pos(sizeOfFft, 3); + + BASOP_cfft_lc3plus(&x[0], &x[1], sizeOfFft2, 2, scale, workBuffer); + + xb0 = L_shr_pos(x[0], 1); + xb1 = L_shr_pos(x[1], 1); + x[0] = L_add(xb0, xb1); + move32(); + x[1] = L_sub(xb0, xb1); + move32(); + + FOR (i = 1; i < sizeOfFft8; i++) + { + RFFT_TWIDDLE1(x, t1, t2, t3, t4, w32[2 * i + 1], w32[2 * i], xb0, xb1, xt0, xt1); + x[2 * i] = L_sub(t1, t3); + move32(); + x[2 * i + 1] = L_sub(t2, t4); + move32(); + x[sizeOfFft - 2 * i] = L_add(t1, t3); + move32(); + x[sizeOfFft - 2 * i + 1] = L_negate(L_add(t2, t4)); + move32(); + } + + FOR (i = sizeOfFft8; i < sizeOfFft4; i++) + { + RFFT_TWIDDLE1(x, t1, t2, t3, t4, w32[(2 * sizeOfFft4 - 2 * i)], w32[(2 * sizeOfFft4 - 2 * i + 1)], xb0, xb1, + xt0, xt1); + x[2 * i] = L_sub(t1, t3); + move32(); + x[2 * i + 1] = L_sub(t2, t4); + move32(); + x[sizeOfFft - 2 * i] = L_add(t1, t3); + move32(); + x[sizeOfFft - 2 * i + 1] = L_negate(L_add(t2, t4)); + move32(); + } + + x[sizeOfFft - 2 * i] = L_shr_pos(x[2 * i + 0], 1); + move32(); + x[sizeOfFft - 2 * i + 1] = L_negate(L_shr_pos(x[2 * i + 1], 1)); + move32(); + + *scale = add(*scale, 1); + move16(); + + Dyn_Mem_Deluxe_Out(); +} + + + +void BASOP_irfftN(Word32 *x, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer) +{ + Dyn_Mem_Deluxe_In(Word16 sizeOfFft2, sizeOfFft4, sizeOfFft8; Word32 t1, t2, t3, t4, xb0, xb1, xt0, xt1; + Word32 * workBuffer; const Word32 *w32; Counter i;); + + workBuffer = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * BASOP_CFFT_MAX_LENGTH */ + + w32 = rfft_twid(sizeOfFft); + + sizeOfFft2 = shr_pos(sizeOfFft, 1); + sizeOfFft4 = shr_pos(sizeOfFft, 2); + sizeOfFft8 = shr_pos(sizeOfFft, 3); + + xb0 = L_shr_pos(x[0], 2); + xb1 = L_shr_pos(x[1], 2); + x[0] = L_add(xb0, xb1); + move32(); + x[1] = L_sub(xb1, xb0); + move32(); + + FOR (i = 1; i < sizeOfFft8; i++) + { + RFFT_TWIDDLE2(x, t1, t2, t3, t4, w32[2 * i + 1], w32[2 * i], xb0, xb1, xt0, xt1); + x[2 * i] = L_sub(t1, t3); + move32(); + x[2 * i + 1] = L_sub(t4, t2); + move32(); + x[sizeOfFft - 2 * i] = L_add(t1, t3); + move32(); + x[sizeOfFft - 2 * i + 1] = L_add(t2, t4); + move32(); + } + + FOR (i = sizeOfFft8; i < sizeOfFft4; i++) + { + RFFT_TWIDDLE2(x, t1, t2, t3, t4, w32[(2 * sizeOfFft4 - 2 * i)], w32[(2 * sizeOfFft4 - 2 * i + 1)], xb0, xb1, + xt0, xt1); + x[2 * i] = L_sub(t1, t3); + move32(); + x[2 * i + 1] = L_sub(t4, t2); + move32(); + x[sizeOfFft - 2 * i] = L_add(t1, t3); + move32(); + x[sizeOfFft - 2 * i + 1] = L_add(t2, t4); + move32(); + } + + x[sizeOfFft - 2 * i] = L_shr_pos(x[2 * i + 0], 1); + move32(); + x[sizeOfFft - 2 * i + 1] = L_shr_pos(x[2 * i + 1], 1); + move32(); + + BASOP_cfft_lc3plus(&x[0], &x[1], sizeOfFft2, 2, scale, workBuffer); + + /* If you want BASOP_irfft to be inverse to BASOP_rfft then the result needs + * to be normalised by sizeOfFft */ + FOR (i = 0; i < sizeOfFft2; i++) + { + x[2 * i + 1] = L_negate(x[2 * i + 1]); + move32(); + } + + *scale = add(*scale, 2); + move16(); + + Dyn_Mem_Deluxe_Out(); +} + + diff --git a/lib_lc3plus/functions.h b/lib_lc3plus/functions.h new file mode 100644 index 000000000..90571c6cd --- /dev/null +++ b/lib_lc3plus/functions.h @@ -0,0 +1,836 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +#include "defines.h" + +#include "stl.h" +#ifdef DYNMEM_COUNT +#include "dynmem.h" +#endif + +#include "basop_util_lc3plus.h" +#include "basop32.h" +#include "constants.h" +#include "lc3.h" +#include "setup_dec_lc3.h" /* for decoder state handle ptr */ +#include "setup_enc_lc3.h" /* for encoder state handle ptr */ +#include "basop_mpy_lc3plus.h" + +#include +#include +#include +#include +#include + +#define PRINTF printf /* C console debug, */ +#define ASSERT(test) assert(test) + +typedef struct +{ + Word16 lead_sign_ind; /* this MPVQ index is the first part of the total PVQ index */ + UWord32 index, size; /* this MPVQ index is the second part of the total PVQ index */ + Word16 dim, k_val; + Word16 vec[PVQ_MAX_VEC_SIZE]; /* integer vector */ +} PvqEntry_fx; + +typedef enum { + LC3_CON_TEC_NS_STD, /* 0 */ + LC3_CON_TEC_PHASE_ECU, /* 2 */ + LC3_CON_TEC_TDPLC, /* 3 */ + LC3_CON_TEC_NS_ADV, /* 4 */ + LC3_CON_TEC_FREQ_MUTING, /* 5 */ +} LC3_ConcealTechnique; + +void WarnMsg(char *msg); +void ExitMsg(char *msg); +void AssertMsg(int true_flag, char *msg); + +void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order[], Word16 *x_e, Word16 BW_stopband_idx, + Word16 frame_dms, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cutoff_idx, Word16 order[], + Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, Word16 frame_dms, + Word16 max_len, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif + , Word16 near_nyquist_flag +); + +void TnsUpdate_fx(Word16 *tns_numfilters, Word16 *long_startfreq, const Word16 **subdiv_startfreq, + const Word16 **subdiv_stopfreq, Word16 frame_length, Word16 tab_idx); + +void processResidualDecoding_fx(Word32 spectrum[], Word16 spectrum_e, Word16 L_spec, UWord8 prm[], Word16 resQBits +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void processPreemph_fx(Word16 *x, Word16 len, Word16 mem[], Word16 memLen, Word16 out[], Word16 *outLen, Word16 mu); + +void processNoiseFilling_fx(Word32 xq[], Word16 nfseed, Word16 xq_e, Word16 fac_ns_idx, Word16 BW_cutoff_idx, + Word16 frame_dms, Word16 fac_ns_pc, Word16 spec_inv_idx, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], +#ifdef ENABLE_HR_MODE + Word32 xq[], +#else + Word16 xq[], +#endif + Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, Word16 frame_dms, Word16 target_bytes, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void processMdctShaping_fx(Word32 x[], +#ifdef ENABLE_HR_MODE + Word32 scf[], +#else + Word16 scf[], +#endif + Word16 scf_exp[], const Word16 bands_offset[], Word16 fdns_npts); + +void processScfScaling(Word16 scf_exp[], Word16 fdns_npts, Word16 *x_e); + +void processMdct_fx( +#ifdef ENABLE_HR_MODE + Word32 x[], +#else + Word16 x[], +#endif + Word16 x_exp, Word16 N, +#ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION +# ifdef ENABLE_HR_MODE + Word16 hrmode, /* i: indicate high precision */ +# endif +#endif +#ifdef ENABLE_HR_MODE + const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ +#else + const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ +#endif + Word16 wLen, +#ifdef ENABLE_HR_MODE + Word32 mem[], /* i/o: last block of input samples */ +#else + Word16 mem[], /* i/o: last block of input samples */ +#endif + Word16 memLen, + Word32 y[], Word16 *y_e, Word8 *scratchBuffer); + +void processLevinson_fx(Word32 *lpc, Word32 *ac, Word16 N, Word16 *rc, Word32 *pred_err, Word8 *scratchBuffer); + +void lpc2rc(Word32 *lpc, Word16 *rc, Word16 N); + +void ProcessingIMDCT(Word32 y[], Word16 *y_e, +#ifdef ENABLE_HR_MODE + const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ + Word32 mem[], /* i/o: overlap add memory */ +#else + const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ + Word16 mem[], /* i/o: overlap add memory */ +#endif + Word16 *mem_e, +#ifdef ENABLE_HR_MODE + Word32 x[], /* o: time signal out */ +#else + Word16 x[], /* o: time signal out */ +#endif + Word16 wLen, + Word16 N, Word16 memLen, Word16 frame_dms, + Word16 concealMethod, Word16 bfi, Word16 prev_bfi, Word16 nbLostFramesInRow, AplcSetup *plcAd, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +#ifdef ENABLE_HR_MODE +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION +void dct_IV(Word32 *pDat, Word16 *pDat_e, Word16 L, Word16 hrmode, Word32 *workBuffer); +# else /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ +void dct_IV(Word32 *pDat, Word16 *pDat_e, Word16 L, Word32 *workBuffer); +# endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ +#else +void dct_IV(Word32 *pDat, Word16 *pDat_e, Word16 L, Word32 *workBuffer); +#endif + +#ifdef ENABLE_HR_MODE +Word16 find_last_nz_pair(const Word32 x[], Word16 length); +#else +Word16 find_last_nz_pair(const Word16 x[], Word16 length); +#endif + +PvqEntry_fx mpvq_index_fx(const Word16 *vec_in, Word16 dim_in, Word16 k_val_local); +void mpvq_deindex_fx(const PvqEntry_fx *entry, UWord32 *h_mem, Word16 *vec_out); + +void pvq_enc_search_fx(const Word16 *x, /* i: target vector to quantize Qin */ + Word16 * rt_far, /* o: outl_far o, raw pulses (non-scaled short) Q0 */ + Word16 * rt_near, /* o: outl_near o, raw pulses (non-scaled short) Q0 */ + Word16 * rtA, /* o: A section raw pulses (non-scaled short) Q0 */ + Word16 * rtB, /* o: B section raw pulses (non-scaled short) Q0 */ + Word32 *L_corr, /* o: 4 un-normalized correlation sums for outl_far, near, outl, A, AB */ + Word32 *L_search_en, /* o: 4 energy sums for out_far, outl_near, A, AB */ + Word16 *pulses_fin, /* i: number of allocated pulses to outl A, AB section */ + Word16 *pulses_proj, /* i: number of proj pulses pulses to outl, A , AB section */ + + const Word16 dim, /* i: Length of vector */ + const Word16 dimA /* i: Length of vector A section */ +); + +PvqEntry_fx get_size_mpvq_calc_offset_fx(Word16 dim_in, Word16 k_val_in, UWord32 *h_mem); + +Word16 pvq_dec_deidx_fx( /* out BER detected 1 , ok==0 */ + Word16 * y, /* o: decoded vector (non-scaled int) */ + const Word16 k_val, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 LS_ind, /* i; lS index 1 bit */ + const UWord32 UL_MPVQ_ind /* i; MPVQ index */ +); + +void pvq_dec_en1_norm_fx( /* */ +#ifdef ENABLE_HR_MODE + Word32 * xq, /* o: en1 normalized decoded vector (Q14) */ +#else + Word16 * xq, /* o: en1 normalized decoded vector (Q14) */ +#endif + const Word16 *y, /* i: decoded vector (non-scaled int) */ + const Word16 kval_max, /* i: max possible K in Q0 kO or kA */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_glob_gain /* i: a Global Gain (negated to fit 1.0 in Q15 as -1.0) */ +); + +#ifdef ENABLE_HR_MODE +#ifdef WIN32 +#define mexPrintf(x, y) printf(x, y) +#endif +#endif + +void pvq_dec_en1_normQ14_fx( /* Have to be used by both encoder and decoder */ +#ifdef ENABLE_HR_MODE + Word32 * xq, /* o: en1 normalized decoded vector (Q14) */ +#else + Word16 * xq, /* o: en1 normalized decoded vector (Q14) */ +#endif + const Word16 *y, /* i: decoded vector (non-scaled int) */ + const Word16 k_val_max, /* i: max possible K in Q0 kO or kA */ + const Word16 dim /* i: Length of vector */ +); + + +#ifdef ENABLE_HR_MODE +void pvq_dec_scale_vec_fx(const Word32 *inQ29, Word16 adjGainQ13, Word32 *outQ); +#else +void pvq_dec_scale_vec_fx(const Word16 *inQ14, Word16 adjGainQ13, Word16 *outQ14); +#endif + +Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side, Word16 mask_side, Word16 nbbits, +#ifdef ENABLE_HR_MODE + Word32 xq[], +#else + Word16 xq[], +#endif + Word16 *tns_order, Word16 tns_numfilters, Word16 *tns_idx, Word16 lastnz, + Word16 *codingdata, UWord8 *resBits, Word16 numResBits, Word16 lsbMode, + Word16 enable_lpc_weighting, Word8 *scratchBuffer); + +void processAriDecoder_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 L_spec, + Word16 fs_idx, Word16 enable_lpc_weighting, Word16 tns_numfilters, Word16 lsbMode, + Word16 lastnz, Word16 *bfi, Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, + Word16 frame_dms, + Word16 n_pc, Word16 be_bp_left, Word16 be_bp_right, Word16 mode, Word16 *spec_inv_idx, + Word16 *b_left, + Word16 *resBits, +#ifdef ENABLE_HR_MODE + Word32 *x, +#else + Word16 *x, +#endif + Word16 *nf_seed, UWord8 *resQdata, Word16 *tns_idx, Word16 *zero_frame, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void processAriDecoderScaling_fx( +#ifdef ENABLE_HR_MODE + Word32 *datain, +#else + Word16 *data16, +#endif + Word16 dataLen, Word32 *data32, Word16 *data_e); + +void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 global_gain_idx, Word16 global_gain_off); + +void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Word16 d_fx_exp, + const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, Word16 frame_dms, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_idx, const Word16 near_nyquist_index, + const Word16 bands_number, const Word32 *ener_fx, const Word16 ener_fx_exp +#ifdef CR8_E_TONE_DETECTOR +#ifdef ENABLE_HR_MODE + , Word16 frame_dms , Word16 hrmode); +#else + ); +#endif +#else + ); +#endif +void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 frame_dms); + +void process_resamp12k8_fx(Word16 x[], Word16 x_len, Word16 mem_in[], Word16 mem_in_len, Word32 mem_50[], + Word16 mem_out[], Word16 mem_out_len, Word16 y[], Word16 *y_len, Word16 fs_idx, + Word16 frame_dms, Word8 *scratchBuffer + , Word16 bps + ); + +void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[], Word16 *pitch, Word16 *s12k8, + Word16 len, Word16 *normcorr, Word16 *mem_pitch, +#ifdef CR9_F_PITCH_WIN_LEN_FIX + Word16 *pitch_flag, +#endif + Word16 s12k8_exp, Word16 frame_dms, Word8 *scratchBuffer); + +void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Word16 *old_wsp_exp, Word16 *old_wsp, + Word16 old_wsplen, Word16 *param, Word16 *wsp, Word16 len, Word16 *mem_normcorr, + Word16 *mem_mem_normcorr, Word16 ol_normcorr, Word16 *mem_ltpf_on, Word16 *mem_ltpf_pitch, + Word16 wsp_exp, Word16 frame_dms, Word8 *scratchBuffer +#ifdef CR9_K_REDUCE_NORM_CORR_TH + ,Word16 hrmode +#endif +); + +void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word16 fs_idx, Word16 old_y_len, + Word16 *old_e, Word16 *x, Word16 *old_x, Word16 *y, Word16 *old_y, Word16 ltpf, + Word16 ltpf_active, Word16 pitch_index, Word16 *old_pitch_int, Word16 *old_pitch_fr, + Word16 *old_gain, Word16 *mem_ltpf_active, Word16 scale_fac_idx, Word16 bfi, + Word16 concealMethod, + Word16 damping, Word16 *old_scale_fac_idx, +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + Word32 *rel_pitch_change, Word16 hrmode, Word16 frame_dms, +#endif + Word8 *scratchBuffer); + +void attack_detector_fx(LC3PLUS_Enc *enc, EncSetup *setup, Word16 *input, Word16 input_scaling, void *scratch); + +void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 *scf, + Word16 scf_smoothing_enabled, Word16 attdec_damping_factor, Word8 *scratchBuffer, Word16 sns_damping + ); + +void processSnsQuantizeScfEncoder_fx(Word16 scf[], /* i: input scf M */ + Word32 *L_prm_idx, /* o: indeces . negative == unused */ +#ifdef ENABLE_HR_MODE + Word32 *scf_q, /* o: quantized scf M */ +#else + Word16 *scf_q, /* o: quantized scf M */ +#endif + Word8 * scratchBuffer); + +Word16 processSnsQuantizeScfDecoder_fx( /* o: BER flag */ + Word32 *L_prm_idx, /* i: indeces */ +#ifdef ENABLE_HR_MODE + Word32 scf_q[], +#else + Word16 scf_q[], +#endif + Word8 *scratchBuffer); /* o: M */ + +void processSnsInterpolateScf_fx( +#ifdef ENABLE_HR_MODE + Word32 *scf_q, Word32 mdct_scf[], +#else + Word16 *scf_q, Word16 mdct_scf[], +#endif + Word16 mdct_scf_exp[], Word16 inv_scf, + Word16 n_bands, Word8 *scratchBuffer); + +void downshift_w32_arr(Word32 *w32_arr, Word16 *w16_arr, Word16 shft_val, Word32 len); +void round_w32tow16_arr(Word32 *w32_arr, Word16 *w16_arr, Word32 len); + +void processPLCmain_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFramesInRow, Word16 bfi, Word16 prev_bfi, + Word16 frame_length, Word16 la_zeroes, +#ifdef ENABLE_HR_MODE + const Word32 w[], +#else + const Word16 w[], +#endif + Word16 x_fx[], Word16 ola_mem[], + Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], + Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, const Word16 *band_offsets, Word16 bands_number, Word16 *damping, + Word16 old_pitch_int, Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, + AplcSetup *plcAd, Word16 frame_dms, Word8 *scratchBuffer, Word16 *pc_nbLostFramesInRow +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + , Word32 rel_pitch_change +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + , Word16 *alpha_type_2_table +#endif + ); + +void processPLCupdate_fx(AplcSetup *plcAd, Word16 x_fx[], Word16 q_fx_exp, Word16 concealMethod, Word16 frame_length, + Word16 fs_idx, Word16 *nbLostFramesInRow, Word16 *prev_prev_bfi, Word16 *prev_bfi, Word16 bfi, + Word16 scf_q[], Word16 *ns_cum_alpha +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif + ); + +void processPLCupdateSpec_fx(Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen); + + +void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], Word16 yLen, + Word16 *PhECU_oold_grp_shape_fx, Word16 *PhECU_old_grp_shape_fx); + +Word32 winEnCalc(const Word16 *, const Word16, const Word16 *, const Word16, const Word16, Word16 *); + +void processPLCUpdateAfterIMDCT_fx(Word16 x_fx[], Word16 q_fx_exp, Word16 concealMethod, Word16 xLen, Word16 fs_idx, + Word16 *nbLostFramesInRow, Word16 *prev_prev_bfi, Word16 *prev_bfi, Word16 bfi, + Word16 scf_q[], Word16 *ns_cum_alpha, AplcSetup *plcAd); + +void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFramesInRow, Word16 bfi, + Word16 ltpf_mem_pitch_int, Word16 frame_length, Word16 frame_dms, Word16 fs_idx, Word16 yLen, + Word16 q_old_d_fx[], const Word16 *band_offsets, Word16 bands_number, AplcSetup *plcAd, Word8 *scratchBuffer +# ifdef ENABLE_HR_MODE + , Word16 hrmode +# endif + ); + +void processPLCapply_fx( +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 *concealMethod, +#else + Word16 concealMethod, +#endif + Word16 nbLostFramesInRow, Word16 bfi, Word16 prev_bfi, + Word16 frame_length, Word16 la_zeroes, +#ifdef ENABLE_HR_MODE + const Word32 w[], +#else + const Word16 w[], +#endif + Word16 x_fx[], Word16 ola_mem[], + Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], + Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, Word16 *damping, Word16 old_pitch_int, + Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, Word16 frame_dms, AplcSetup *plcAd, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + , Word32 rel_pitch_change + +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + , Word16 *alpha_type_2_table +#endif + ); + +void processPLCNoiseSubstitution_fx(Word32 spec[], Word16 spec_prev[], Word16 L_spec); +void processPLCDampingScrambling_main_fx(Word16 bfi, Word16 concealMethod, Word16 ns_nbLostFramesInRow, Word16 *cum_fflcAtten, + Word16 pc_nbLostFramesInRow, Word16 *ns_seed, Word16 *pc_seed, Word16 pitch_present_bfi1, + Word16 pitch_present_bfi2, Word32 spec[], Word16 *q_fx_exp, Word16 *q_old_d_fx, + Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, Word16 frame_dms, + Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 spec_inv_idx +#ifdef CR8_A_PLC_FADEOUT_TUNING + , UWord8 plc_fadeout_type +#endif + ); + +void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostFramesInRow, Word16 stabFac, Word16 processDampScramb, + Word16 *cum_fflcAtten, Word16 pitch_present, Word16 frame_dms, Word16 *cum_fading_slow, + Word16 *cum_fading_fast, Word16 *seed, Word16 spec_inv_idx +#ifdef CR8_A_PLC_FADEOUT_TUNING + , UWord8 plc_fadeout_type +#endif + ); + +void processLagwin_fx(Word32 r[], const Word32 w[], Word16 m); + +void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 d2_fx_exp, Word16 n_bands, + Word16 lpc_order, Word8 *scratchBuffer); + +void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 frame_dms, + Word8 *scratchBuffer); + +void processPLCLpcScaling_fx(Word32 tdc_A_32[], Word16 tdc_A_16[], Word16 m); + +void processPLCcomputeStabFac_main(Word16 scf_q[], Word16 old_scf_q[], Word16 old_old_scf_q[], Word16 bfi, + Word16 prev_bfi, Word16 prev_prev_bfi, Word16 *stab_fac); + +void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, + Word16 *xfp_fx, Word16 xfp_exp_fx,Word16 margin_xfp, + Word16 fs_idx, + Word32 *L_oold_xfp_w_E_fx, Word16 *oold_xfp_w_E_exp_fx, + Word32 *L_old_xfp_w_E_fx, Word16 *old_xfp_w_E_exp_fx, + Word16 *oold_Ltot_exp_fx, Word16 *old_Ltot_exp_fx); + +void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 preemphFac_fx, const Word16 *A_fx, + const Word16 lpc_order, const Word16 *pcmbufHist_fx, + const Word16 frame_length, const Word16 frame_dms, const Word16 fs_idx, + const Word16 nbLostFramesInRow, const Word16 overlap, + const Word16 stabFac_fx, Word16 *fract, Word16 *seed_fx, + Word32 *gain_c_fx, Word16 *synth_fx, Word16 *Q_syn, + Word16 *alpha, Word16 max_len_pcm_plc, + Word16 harmonicBuf_fx[MAX_PITCH], Word16 synthHist_fx[M], Word16 *const harmonicBuf_Q, + Word8 *scratchBuffer +#ifdef CR9_I_INC_TDC_FADEOUT_LEN + ,UWord8 plc_fadeout_type +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + ,Word16 *alpha_type_2_table +#endif +); + +void processTdac_fx(Word16 *ola_mem, Word16 *ola_mem_exp, const Word16 *synth, const Word16 synth_exp, +#ifdef ENABLE_HR_MODE + const Word32 *win, +#else + const Word16 *win, +#endif + const Word16 la_zeroes, const Word16 frame_len, Word8 *scratchBuffer); + +void plc_phEcu_F0_refine_first_fx(Word16 *plocs, const Word16 n_plocs_in, Word32 *L_f0est, + const Word16 stPhECU_f0hzLtpBinQ7, const Word16 stPhECU_f0gainLtpQ15, + const Word16 nSubm); +void plc_phEcu_LF_peak_analysis_fx(Word16 *plocs, Word16 *n_plocs, Word32 *L_f0estQ16, const Word16 *mag, + const Word16 stPhECU_f0hzLtpBinQ7, const Word16 stPhECU_f0gainLtpQ15, + const Word16 nSubm, Word16 maxPlocs, Word8 *scratchBuffer); + +Word16 plc_phEcuSetF0Hz_fx(Word16 fs_idx, Word16 old_pitch_int, Word16 old_pitch_fr); + +void create_sin2_taper_fx(Word16 *, Word16, Word16); + +void plc_phEcu_initWord16(Word16 * vec, /*i/o : vector pointer */ + const Word16 value, /*i : short initialization value */ + const Word16 len); /*i : number of elements */ + +Word16 plc_phEcu_ratio_fx(const Word32, const Word32, Word16 *); + +void plc_phEcu_minval_fx(const Word16 *inp, /* i : vector */ + const Word16 len, /* i : length */ + Word16 * minvalPtr); /* o : min value Ptr */ + +void plc_phEcu_maxval_fx(const Word16 *inp, /* i : vector */ + const Word16 len, /* i : length */ + Word16 * maxvalPtr); /* o : *maxvalPtr */ + +void Scale_sig_sat(Word16 x[], /* i/o: signal to scale, possibly saturated Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0); /* i : exponent: x = round(x << exp) Qx ?exp */ + +void Processing_ITDA_WIN_OLA(Word32 L_x_tda[], Word16 *y_e, +#ifdef ENABLE_HR_MODE + const Word32 w[], +#else + const Word16 w[], +#endif + Word16 mem[], Word16 *mem_e, Word16 x[], + Word16 wLen, Word16 N, Word16 memLen); + +void trans_burst_ana_fx(const Word16 *xfp, /* i : Input signal Qspec */ + Word16 * mag_chg, /* o : Magnitude modification Q15 */ + Word16 *ph_dith, /* o : Phase dither, 2*PI is not included (Q15, i.e., between 0.0 and 1.0) */ + Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients Q15 */ + const Word16 output_frame, /* i : Frame length */ + const Word16 time_offs, /* i : Time offset (integral multiple of output_frame) */ + const Word16 est_stab_content, /* i : 0.0=dynamic ... 1.0=stable (==st->env_stab ) */ + Word16 * alpha, /* o : Magnitude modification factors for fade to average */ + Word16 * beta, /* : Magnitude modification factors for fade to average */ + Word16 * beta_mute, /* i/o : Factor for long-term mute */ + Word16 * Xavg, /* o : Frequency group average gain to fade to */ + Word16 Q_spec, Word32 L_oold_xfp_w_E_fx, Word16 oold_xfp_w_E_exp_fx, Word16 oold_Ltot_exp_fx, + Word16 *oold_grp_shape_fx, Word32 L_old_xfp_w_E_fx, Word16 old_xfp_w_E_exp_fx, + Word16 old_Ltot_exp_fx, Word16 *old_grp_shape_fx, +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 fadeout, + Word32 *L_Xavg, /* full scale average band amplitudes */ +#endif + Word8 *scratchBuffer); + +void spec_ana_fx(Word16 *xfp, Word16 *, Word32 *, Word16 *, Word16 *, const Word16, const Word16, + const Word16 *, const Word16, const Word16, Word16 maxLprot, Word16 maxPlocs, Word8 *scratchBuffer); + +void subst_spec_fx(const Word16 *, const Word32 *, Word16 *, const Word16, Word16 *, const Word16 *, const Word16, + const Word16 *, const Word16, Word16 *, const Word16 *, const Word16 *, const Word16 *, const Word16 +#ifdef CR8_A_PLC_FADEOUT_TUNING + ,const Word16, + Word16*, + const Word32 * +#endif +); + +void rec_frame_fx(Word16 * X, /* i : FFT spectrum */ + Word32 * L_ecu_rec, /* o : Reconstructed frame in tda domain */ + const Word16 output_frame, /* i : Frame length */ + const Word16 Q, const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + + Word16 maxLprot, const Word16 *prevsynth, const Word16 Q_prevsynth, + Word8 * scratchBuffer); + +Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F); + +void hq_phase_ecu_fx(const Word16 *prevsynth, /* i : buffer of previously synthesized signal */ + Word32 *L_ecu_rec, /* o : reconstructed frame in tda domain , also tmp w32_fft buffer */ + Word16 *time_offs, /* i/o: Sample offset for consecutive frame losses*/ + Word16 *X_sav, /* i/o: Stored spectrum of prototype frame */ + Word16 *Q_spec, /* o: Q value of stored spectrum */ + Word16 *num_p, /* i/o: Number of identified peaks */ + Word16 *plocs, /* i/o: Peak locations */ + Word32 *L_plocsi, /* i/o: Interpolated peak locations Q16 */ + const Word16 env_stab, /* i : Envelope stability parameter */ + const Word16 f0hzLtpBinQ7, /* i: LTP bin frequency in normalized Hz Q7 */ + const Word16 norm_corrQ15_fx, /*i : correlation for lag at f0hzLtpBinQ7 */ + const Word16 prev_bfi, /* i : indicating burst frame error */ + Word16 old_is_transient[2], /* i/o : flags indicating noise generation */ + Word16 * mag_chg_1st, /* i/o: per band magnitude modifier for transients */ + Word16 * mag_chg_gr, /* o: per band magnitude modifier incl burst attenuation */ + Word16 * Xavg, /* i/o: Frequency group average gain to fade to */ + Word16 * beta_mute, /* o : Factor for long-term mute */ + const Word16 bwidth_fx, /* i : Encoded bandwidth */ + const Word16 output_frame, /* i : frame length */ + Word16 * seed_out_fxPtr, /* o: seed synch analysis */ + Word16 * X_out, /* o: utput evolved spectrum */ + const Word16 t_adv, /* i : time adjustment including time_offs */ + const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + const Word16 * sp_ana_win, /* i : whr hamming window */ + Word16 q_fx_old_exp, Word16 maxLprot, Word16 maxPlocs, + Word32 L_oold_xfp_w_E_fx, Word16 oold_xfp_w_E_exp_fx, /* exp of time signal */ + Word16 oold_Ltot_exp_fx, /*true exp of energy */ + Word16 *oold_grp_shape_fx, Word32 L_old_xfp_w_E_fx, + Word16 old_xfp_w_E_exp_fx, /* exp of time signal */ + Word16 old_Ltot_exp_fx, /*true exp of energy */ + Word16 *old_grp_shape_fx, + Word16 margin_prev_synth, /* i: margin in prev_synth(16ms for first bfi , 3.75 ms for other bfi + frames ) , from plcAd.PhECU_margin_xfp */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + const Word16 fadeout, /*i: fadeout length indicator */ + Word16 *nonpure_tone_flag_ptr, /* i/o : non-pure single tone indicator state */ +#endif + Word8 *scratchBuffer /* Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */ +); + +Word16 +plc_xcorr_lc_fx(/* o: quantized output xcorr in Q15 [ 0 ..32767 ] = [0. 1.0[ */ + Word16 * + pcmbuf_fx, /* NB should be an already dynamically upscaled buffer with about 0...1 bits margin */ + Word16 max_len_pcm_plc, /* Q0 size of pcmbuf_fx */ + Word16 pitch_int, /* Q0 in Fs, lag value to evaluate, corresponding to the current f0 fr pcm_buf */ + Word16 fs_idx); + +void plc_phEcu_peak_locator_fx(const Word16 *, const Word16, Word16 *, Word16 *, const Word16, const Word16, + const Word16, Word16, Word8 *); + +Word16 plc_phEcu_find_ind_fx(const Word16 *, const Word16, const Word16); + + +Word16 initQV(Word16 SR_idx, Word32 BR); + +void processEstimateGlobalGain_fx(Word32 x[], Word16 x_e, Word16 lg, Word16 sqTargetBits, +#ifdef ENABLE_HR_MODE + Word32 *gain, +#else + Word16 *gain, +#endif + Word16 *gain_e, + Word16 *quantizedGain, Word16 *quantizedGainMin, Word16 quantizedGainOff, + Word32 *targetBitsOff, Word16 *old_targetBits, Word16 old_specBits, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode, Word16 regBits, Word16 frame_dms +#endif +); + +void processAdjustGlobalGain_fx(Word16 *gg_idx, Word16 gg_idx_min, Word16 gg_idx_off, +#ifdef ENABLE_HR_MODE + Word32 *gain, +#else + Word16 *gain, +#endif + Word16 *gain_e, + Word16 target, Word16 nBits, Word16 *gainChange, Word16 fs_idx +#ifdef ENABLE_HR_MODE + , Word16 hrmode, Word16 frame_dms +#endif + ); + +void processScalarQuant_fx(Word32 x[], Word16 x_e, Word16 xq[], Word16 L_frame, Word16 gain, Word16 gain_e); + +#ifdef ENABLE_HR_MODE +void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word32 gain, Word16 gain_e, Word32 xq[], Word16 nt, Word16 target, + Word16 totalBits, Word16 *nBits, Word16 *nBits2, Word16 fs_idx, Word16 *lastnz, + Word16 *codingdata, Word16 *lsbMode, Word16 mode, Word16 hrmode); +#else +void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, Word16 xq[], Word16 nt, + Word16 target, + Word16 totalBits, Word16 *nBits, Word16 *nBits2, Word16 fs_idx, Word16 *lastnz, + Word16 *codingdata, Word16 *lsbMode, Word16 mode); + +#endif /* ENABLE_HR_MODE */ + +void processResidualCoding_fx(Word16 x_e, Word32 x[], +#ifdef ENABLE_HR_MODE + Word32 xq[], Word32 gain, +#else + Word16 xq[], Word16 gain, +#endif + Word16 gain_e, Word16 L_spec, Word16 targetBits, Word16 nBits, + UWord8 *resBits, Word16 *numResBits +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +); + +void scale_signal24_fx(Word32 x[], /* i: time input signal */ +#ifdef ENABLE_HR_MODE + Word32 x_scaled[], +#else + Word16 x_scaled[], +#endif + Word16 *x_exp, +#ifdef ENABLE_HR_MODE + Word32 mdct_mem[], +#else + Word16 mdct_mem[], +#endif + Word16 mdct_mem_len, + Word16 resample_mem_in[], Word16 resample_mem_in_len, Word32 resample_mem_in50[], + Word16 resample_mem_out[], Word16 resample_mem_out_len, Word32 mdct_mem32[], Word16 N, + Word32 resamp_mem32[], Word16 mem_s12k8[], Word16 *resamp_scale); + +void processReorderBitstream_fx(UWord8 *bytes, Word16 n_pccw, Word16 n_pc, Word16 b_left, Word8 *scratchBuffer); + +/* al_fec.c */ +Word16 fec_get_n_pccw(Word16 slot_bytes, Word16 fec_mode, Word16 ccc_flag); +Word16 fec_get_data_size(Word16 fec_mode, Word16 ccc_flag, Word16 slot_bytes); +Word16 fec_get_n_pc(Word16 fec_mode, Word16 n_pccw, Word16 slot_bytes); + +void fec_encoder(Word16 mode, Word16 epmr, UWord8 *iobuf, Word16 data_bytes, Word16 slot_bytes, Word16 n_pccw, + void *scratch); + +int fec_decoder(UWord8 *iobuf, Word16 slot_bytes, int *data_bytes, Word16 *epmr, Word16 ccc_flag, Word16 *n_pccw, + int *bfi, Word16 *be_bp_left, Word16 *be_bp_right, Word16 *n_pc, Word16 *m_fec, void *scratch); + +void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, Word16 frame_dms, Word16 q_old_res_fx[], + Word16 *q_old_res_fx_exp, +#ifdef ENABLE_HR_MODE + Word32 q_res_fx[], +#else + Word16 q_res_fx[], +#endif + Word16 q_old_d_fx[], Word16 spec_inv_idx, + Word16 pitch_present, Word16 stab_fac, Word32 q_d_fx[], Word16 *q_fx_exp, + Word16 gg_idx, Word16 gg_idx_off, Word16 *prev_gg, Word16 *prev_gg_e, Word16 *BW_cutoff_idx_nf, + Word16 *prev_BW_cutoff_idx_nf, Word16 fac_ns_idx, Word16 *prev_fac_ns_fx, Word16 *pc_nbLostFramesInRow); +void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[], + Word16 yLen, Word16 spec_inv_idx, Word16 stab_fac, Word16 *bfi); +void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp, +#ifdef ENABLE_HR_MODE + Word32 q_res_fx[], +#else + Word16 q_res_fx[], +#endif + Word16 q_old_d_fx[], Word16 spec_inv_idx, Word16 *fac, Word16 *fac_e, Word32 q_d_fx[], + Word16 *q_fx_exp, Word16 gg_idx, Word16 gg_idx_off, Word16 prev_gg, Word16 prev_gg_e, + Word16 *pc_nbLostFramesInRow); +void processPCupdate_fx(Word16 bfi, Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp, +#ifdef ENABLE_HR_MODE + Word32 q_res_fx[], +#else + Word16 q_res_fx[], +#endif + Word16 spec_inv_idx, Word16 gg_idx, Word16 gg_idx_off, Word16 *prev_gg, Word16 *prev_gg_e, + Word16 rframe, Word16 *BW_cutoff_idx_nf, Word16 *prev_BW_cutoff_idx_nf, Word16 fac_ns_idx, + Word16 *prev_fac_ns_fx, Word16 fac, Word16 fac_e); +void processPcApplyDamping_fx(Word32 x[], Word16 xLen, Word16 fac, Word16 spec_inv_idx); + +void process_cutoff_bandwidth(Word32 d_fx[], Word16 len, Word16 bw_bin); + +void idct16_fx(const Word16 *in, Word16 *out); + +void dct32_fx(const Word32 *in, Word32 *out); +void idct32_fx(const Word32 *in, Word32 *out); +void idct32_32_fx(const Word32 *in, Word32 *out); + +/* Functions used in arithmetic coder */ + +void write_bit_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 bit); +void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, Word16 numbits); + +void processEncoderEntropy(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 targetBytes, + Word16 L_spec, Word16 BW_cutoff_bits, Word16 tns_numfilters, Word16 lsbMode, Word16 lastnz, + Word16 *tns_order, Word16 fac_ns_idx, Word16 gg_idx, Word16 BW_cutoff_idx, Word16 *ltpf_idx, + Word32 *L_scf_idx, Word16 bfi_ext, Word16 fs_idx); + +void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 nbbits, Word16 L_spec, + Word16 fs_idx, Word16 BW_cutoff_bits, Word16 *tns_numfilters, Word16 *lsbMode, + Word16 *lastnz, Word16 *bfi, Word16 *tns_order, Word16 *fac_ns_idx, Word16 *gg_idx, + Word16 *BW_cutoff_idx, Word16 *ltpf_idx, Word32 *L_scf_idx, Word16 frame_dms); + +#ifdef ENABLE_PADDING +int paddingDec_fx(UWord8 *bytes, Word16 nbbits, Word16 L_spec, Word16 BW_cutoff_bits, Word16 ep_enabled, + Word16 *total_padding, Word16 *np_zero); +#endif + +Word16 read_bit(UWord8 *ptr, Word16 *bp, Word16 *mask); + +/* setup_enc_lc3.c */ +int alloc_encoder(LC3PLUS_Enc *encoder, int samplerate, int channels); +void set_enc_frame_params(LC3PLUS_Enc *encoder); +LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate); +LC3PLUS_Error FillEncSetup(LC3PLUS_Enc *encoder, int samplerate, int channels +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + , int32_t lfe_channel_array[] + ); + +/* setup_dec_lc3.c */ +int alloc_decoder(LC3PLUS_Dec *decoder, int samplerate, int channels); +void set_dec_frame_params(LC3PLUS_Dec *decoder); +LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes); +LC3PLUS_Error FillDecSetup(LC3PLUS_Dec *decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + ); + +int Enc_LC3PLUS(LC3PLUS_Enc *encoder, void **input, int bits_per_sample, UWord8 *output, void *scratch, Word16 bfi_ext); +LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int input_bytes, void **output, int bits_per_sample, void *scratch, + int bfi_ext); + +void *balloc(void *base, size_t *base_size, size_t size); + +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR +Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms); +#endif + +#endif diff --git a/lib_lc3plus/imdct_fx.c b/lib_lc3plus/imdct_fx.c new file mode 100644 index 000000000..50ad2b257 --- /dev/null +++ b/lib_lc3plus/imdct_fx.c @@ -0,0 +1,387 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void ProcessingIMDCT( + Word32 y[], /* i: spectra data */ + Word16 * y_e, /* i: spectral data exponent */ +#ifdef ENABLE_HR_MODE + const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ + Word32 mem[], /* i/o: overlap add memory */ +#else + const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ + Word16 mem[], /* i/o: overlap add memory */ +#endif + Word16 * mem_e, /* i/o: overlap add exponent */ +#ifdef ENABLE_HR_MODE + Word32 x[], /* o: time signal out */ +#else + Word16 x[], /* o: time signal out */ +#endif + Word16 wLen, /* i: window length */ + Word16 N, /* i: block size */ + Word16 memLen, /* i: overlap add buffer size */ + Word16 frame_dms, /* i: frame size in ms */ + Word16 concealMethod, /* i: concealment method */ + Word16 bfi, /* i: bad frame indicator */ + Word16 prev_bfi, /* i: previous bad frame indicator */ + Word16 nbLostFramesInRow, /* i: number of consecutive lost frames */ + AplcSetup *plcAd, /* i: advanced plc struct */ + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +) +{ + Counter i; + Word16 o, z, m, s; + Word16 y_s, mem_s, max_bw; + Word32 L_tmp; + Word32 *workBuffer; + +#ifdef DYNMEM_COUNT + struct _dynmem + { + Word16 o, z, m, s; + Word16 y_s, mem_s, max_bw; + Word32 L_tmp; + Counter i; + Word32 *workBuffer; + Word16 mem_i_win; + Word16 w_taper_win; + }; + Dyn_Mem_In("ProcessingIMDCT", sizeof(struct _dynmem)); +#endif + + + test(); test(); test(); + IF (sub(bfi, 1) != 0 || sub(concealMethod, LC3_CON_TEC_NS_STD) == 0 || sub(concealMethod, LC3_CON_TEC_NS_ADV) == 0 || sub(concealMethod, LC3_CON_TEC_FREQ_MUTING) == 0) + { + workBuffer = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN bytes */ + + /* Init (constant per sample rate) */ + z = 2 * N - wLen; /* number of leading zeros in window */ + m = N >> 1; /* half block size */ + o = m - z; + max_bw = 0; + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + max_bw = N; + } + else +#endif + { + SWITCH (frame_dms) + { + case 25: + max_bw = MAX_BW >> 2; move16(); + BREAK; + case 50: + max_bw = MAX_BW >> 1; move16(); + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + max_bw = (MAX_BW >> 2) * 3; move16(); + BREAK; +#endif + case 100: + max_bw = MAX_BW; move16(); + BREAK; + } + } + + if (N > max_bw) + basop_memset(&y[max_bw], 0, (N - max_bw) * sizeof(*y)); + + /* Start Processing */ + y_s = getScaleFactor32_0(y, N); + IF (sub(y_s, 32) < 0) + { + FOR (i = 0; i < N; i++) + { + y[i] = L_shl(y[i], y_s); + } + *y_e = sub(*y_e, y_s); +#ifdef ENABLE_HR_MODE + dct_IV(y, y_e, N, +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + hrmode, +# endif + workBuffer); +#else + dct_IV(y, y_e, N, workBuffer); +#endif + y_s = getScaleFactor32_lc3plus(y, N); + y_s = sub(y_s, 1); + *y_e = sub(*y_e, y_s + 3); /* mdct window is scaled by pow(2,x) */ + /* N<=20 only happens for 2.5ms frames in NB */ + if (sub(N, 20) <= 0) + { + *y_e = add(*y_e, 2); + } + else if (sub(N, 120) <= 0) + { + *y_e = add(*y_e, 1); + } + } + ELSE + { + *y_e = 0; move16(); + } + +#ifdef ENABLE_HR_MODE + mem_s = getScaleFactor32_0(mem, memLen); +#else + mem_s = getScaleFactor16_0(mem, memLen); +#endif + +#ifdef ENABLE_HR_MODE + IF (sub(mem_s, 32) < 0) +#else + IF (sub(mem_s, 16) < 0) +#endif + { + mem_s = sub(mem_s, 1); + *mem_e = sub(*mem_e, mem_s); + } + ELSE + { + *mem_e = *y_e; move16(); + } + + s = sub(*mem_e, *y_e); + + IF (s > 0) + { + y_s = sub(y_s, s); + *y_e = add(*y_e, s); + } + ELSE + { + mem_s = add(mem_s, s); + *mem_e = sub(*mem_e, s); + } + + mem_s = s_max(mem_s, -31); + y_s = s_max(y_s, -31); + + if (sub(y_s, 32) >= 0) + { + y_s = 0; move16(); + } +#ifdef ENABLE_HR_MODE + if (sub(mem_s, 32) >= 0) + { + mem_s = 0; move16(); + } +#else + if (sub(mem_s, 16) >= 0) + { + mem_s = 0; move16(); + } +#endif + + UNUSED(prev_bfi); + UNUSED(nbLostFramesInRow); + UNUSED(plcAd); + + { /* regular operation */ + FOR (i = 0; i < o; i++) + { +#ifdef ENABLE_HR_MODE + L_tmp = L_sub(L_shl(mem[i], mem_s), Mpy_32_32_lc3plus(L_shl(y[m + i + z], y_s), w[4 * m - 1 - i - z])); + x[i] = L_tmp; + move32(); +#else + L_tmp = L_sub(L_shl(L_deposit_h(mem[i]), mem_s), Mpy_32_16_lc3plus(L_shl(y[m + i + z], y_s), w[4 * m - 1 - i - z])); + x[i] = round_fx(L_tmp); + move16(); +#endif + } + FOR (i = 0; i < m; i++) + { +#ifdef ENABLE_HR_MODE + L_tmp = L_add(L_shl(mem[i + o], mem_s), Mpy_32_32_lc3plus(L_shl(y[2 * m - 1 - i], y_s), w[3 * m - 1 - i])); + x[i + o] = L_tmp; + move32(); +#else + L_tmp = L_add(L_shl(L_deposit_h(mem[i + o]), mem_s), Mpy_32_16_lc3plus(L_shl(y[2 * m - 1 - i], y_s), w[3 * m - 1 - i])); + x[i + o] = round_fx(L_tmp); + move16(); +#endif + } + } + + FOR (i = 0; i < m; i++) + { +#ifdef ENABLE_HR_MODE + L_tmp = L_negate(Mpy_32_32_lc3plus(L_shl(y[i], y_s), w[m - 1 - i])); + x[3 * m - z + i] = L_tmp; + move32(); +#else + L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(y[i], y_s), w[m - 1 - i])); + x[3 * m - z + i] = round_fx(L_tmp); + move16(); +#endif + } + + FOR (i = 0; i < m; i++) + { +#ifdef ENABLE_HR_MODE + L_tmp = L_negate(Mpy_32_32_lc3plus(L_shl(y[i], y_s), w[m + i])); + x[3 * m - z - 1 - i] = L_tmp; + move32(); +#else + L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(y[i], y_s), w[m + i])); + x[3 * m - z - 1 - i] = round_fx(L_tmp); + move16(); +#endif + } + +#ifdef ENABLE_HR_MODE + basop_memmove(mem, &x[N], memLen * sizeof(Word32)); +#else + basop_memmove(mem, &x[N], memLen * sizeof(Word16)); +#endif + + *mem_e = *y_e; move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} +/* End Processing */ + +void Processing_ITDA_WIN_OLA( + Word32 L_x_tda[], /* i: X_TDA buffer data = "y" DCT-IV output */ + Word16 * y_e, /* i/o: x_tda input exponent "y_e" , x output exponent */ +#ifdef ENABLE_HR_MODE + const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ +#else + const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ +#endif + Word16 mem[], /* i/o: overlap add memory */ + Word16 * mem_e, /* i/o: overlap add exponent */ + Word16 x[], /* o: time signal out */ + Word16 wLen, /* i: window length */ + Word16 N, /* i: block size */ + Word16 memLen /* i: overlap add buffer size */ + ) +{ + /* Declarations */ + Word16 i, o, z, m, s; + Word16 y_s, mem_s; + Word32 L_tmp; + Word32 *L_y; + Word16 fs_idx, tmp_w, w_factor; + Word16 factorITDA[5]= { 25905 , 18318 , 22435 , 25905 , 31727}; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("Processing_ITDA_WIN_OLA", sizeof(struct { + Word16 i, o, z, m, s; + Word16 y_s, mem_s; + Word32 L_tmp; + Word32 *L_y; + })); +#endif + + + /* Init (constants per sample rate) */ + z = 2 * N - wLen; /* number of leading zeros in window */ + m = N >> 1; /* half block size */ + o = m - z; + + + L_y = L_x_tda; /* use same variables naming as in IMDCT for DCT-IV output signal y */ + + y_s = getScaleFactor32_lc3plus(L_y, N); + + y_s = sub(y_s, 1); /* add 1 bit margin , y_s is now initial tda upscaling factor */ + + + *y_e = sub(add(*y_e,1),y_s); /* handle W scale down by 2^(3) , as mdct synthesis window was upscaled by pow(2,x) x=2 for NB otherwise 3 */ + + + + mem_s = getScaleFactor16_0(mem, memLen); + + IF (sub(mem_s, 16) < 0) + { + mem_s = sub(mem_s, 1); /* one bit margin */ + *mem_e = sub(*mem_e, mem_s); /*adjusted mem exponent due to new scale */ + } + ELSE + { + *mem_e = 0; move16(); + } + + s = sub(*mem_e, *y_e); /* */ + + IF (s > 0) + { + y_s = sub(y_s, s); /* new , reduced upshift of TDA in window application loop */ + *y_e = add(*y_e, s); /* resulting new exp y_e for output signal */ + } + ELSE + { + mem_s = add(mem_s, s); /* s negative or zero, new , decreased upshift of OLAmem in loop */ + *mem_e = sub(*mem_e, s); /* resulting new exp mem_e for OLA_mem output signal */ + } + + fs_idx = mult(N,(Word16)(32768.0/99.0)); /* truncation needed , i.e no rounding can be applied here */ + w_factor = factorITDA[fs_idx]; move16(); + y_s = s_max(s_min(y_s, 31), -31); + + FOR (i = 0; i < o; i++) + { + tmp_w = mult_r(extractW16(w[4 * m - 1 - i - z]), w_factor); + L_tmp = L_sub(L_shl_sat(L_deposit_h(mem[i]), mem_s), Mpy_32_16_lc3plus(L_shl(L_y[m + i + z], y_s), tmp_w)); + x[i] = round_fx_sat(L_tmp); + move16(); + } + + FOR (i = 0; i < m; i++) + { + tmp_w = mult_r(extractW16(w[3 * m - 1 - i]), w_factor); + L_tmp = L_add(L_shl_sat(L_deposit_h(mem[i + o]), mem_s), Mpy_32_16_lc3plus(L_shl(L_y[2 * m - 1 - i], y_s), tmp_w)); + x[i + o] = round_fx_sat(L_tmp); + move16(); + } + + FOR (i = 0; i < m; i++) + { + tmp_w = mult_r(extractW16(w[m - 1 - i]), w_factor); + L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(L_y[i], y_s), tmp_w)); + x[3 * m - z + i] = round_fx(L_tmp); move16(); + } + + FOR (i = 0; i < m; i++) + { + tmp_w = mult_r(extractW16(w[m + i]), w_factor); + L_tmp = L_negate(Mpy_32_16_lc3plus(L_shl(L_y[i], y_s), tmp_w )); + x[3 * m - z - 1 - i] = round_fx(L_tmp); move16(); + } + + FOR (i = 0; i < memLen; i++) + { + mem[i] = x[N + i]; move16(); + } + *mem_e = *y_e; move16(); /* set OLA mem exp to x_Fx exponent*/ + + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/lc3.c b/lib_lc3plus/lc3.c new file mode 100644 index 000000000..120dd0929 --- /dev/null +++ b/lib_lc3plus/lc3.c @@ -0,0 +1,426 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" +#include "lc3.h" +#include "setup_dec_lc3.h" +#include "setup_enc_lc3.h" + +#define RETURN_IF(cond, error) \ + if (cond) \ + return (error) + +#ifdef SUBSET_NB +#pragma message("- SUBSET_NB") +#endif +#ifdef SUBSET_WB +#pragma message("- SUBSET_WB") +#endif +#ifdef SUBSET_SSWB +#pragma message("- SUBSET_SSWB") +#endif +#ifdef SUBSET_SWB +#pragma message("- SUBSET_SWB") +#endif +#ifdef SUBSET_FB +#pragma message("- SUBSET_FB") +#endif +#ifdef SUBSET_UB +#pragma message("- SUBSET_UB") +#endif + +/* ensure api header constants are up to date */ +STATIC_ASSERT(LC3PLUS_MAX_SAMPLES >= MAX_LEN); +STATIC_ASSERT(LC3PLUS_MAX_CHANNELS >= MAX_CHANNELS); +STATIC_ASSERT(LC3PLUS_MAX_BYTES >= BYTESBUFSIZE); +STATIC_ASSERT(LC3PLUS_ENC_MAX_SIZE >= ENC_MAX_SIZE); +STATIC_ASSERT(LC3PLUS_DEC_MAX_SIZE >= DEC_MAX_SIZE); +STATIC_ASSERT(LC3PLUS_ENC_MAX_SCRATCH_SIZE >= SCRATCH_BUF_LEN_ENC_TOT); +STATIC_ASSERT(LC3PLUS_DEC_MAX_SCRATCH_SIZE >= SCRATCH_BUF_LEN_DEC_TOT); +STATIC_ASSERT(PLC_FADEOUT_IN_MS >= 20); + + +/* misc functions ************************************************************/ + +int lc3plus_version(void) +{ + return LC3PLUS_VERSION; +} + +int lc3plus_channels_supported(int channels) +{ + return channels >= 1 && channels <= MAX_CHANNELS; +} + +int lc3plus_samplerate_supported(int samplerate) +{ + switch (samplerate) + { +#ifdef SUBSET_NB + case 8000: return 1; +#endif +#ifdef SUBSET_WB + case 16000: return 1; +#endif +#ifdef SUBSET_SSWB + case 24000: return 1; +#endif +#ifdef SUBSET_SWB + case 32000: return 1; +#endif +#ifdef SUBSET_FB + case 44100: return 1; + case 48000: return 1; +#endif +#ifdef ENABLE_HR_MODE + case 96000: return 1; +#endif + default: return 0; + } +} + +static int lc3plus_plc_mode_supported(LC3PLUS_PlcMode plc_mode) +{ + switch ((int)plc_mode) + { + case LC3PLUS_PLC_ADVANCED: /* fallthru */ + return 1; + default: return 0; + } +} + +static int lc3plus_frame_size_supported(int frame_dms) +{ + switch (frame_dms) + { + case 25: /* fallthru */ + case 50: /* fallthru */ +#ifdef CR8_G_ADD_75MS + case 75: /* fallthru */ +#endif + case 100: + return 1; + default: return 0; + } +} + +static int null_in_list(void **list, int n) +{ + while (--n >= 0) + RETURN_IF(list[n] == NULL, 1); + return 0; +} + +/* return pointer to aligned base + base_size, *base_size += size + 4 bytes align */ +void *balloc(void *base, size_t *base_size, size_t size) +{ + uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & ~3; + assert((uintptr_t)base % 4 == 0); /* base must be 4-byte aligned */ + *base_size = (*base_size + size + 3) & ~3; + return (void *)ptr; +} + +int32_t lc3_enc_supported_lfe(void) +{ + return 1; +} + +/* encoder functions *********************************************************/ + +LC3PLUS_Error lc3plus_enc_init(LC3PLUS_Enc *encoder, int samplerate, int channels +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + , int32_t lfe_channel_array[] + ) +{ + int ch = 0; + + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF((uintptr_t)encoder % 4 != 0, LC3PLUS_ALIGN_ERROR); + RETURN_IF(!lc3plus_samplerate_supported(samplerate), LC3PLUS_SAMPLERATE_ERROR); + RETURN_IF(!lc3plus_channels_supported(channels), LC3PLUS_CHANNELS_ERROR); +#ifdef ENABLE_HR_MODE + RETURN_IF(samplerate==96000 && hrmode == 0, LC3PLUS_HRMODE_ERROR); +#endif + + for (ch = 0; ch < channels; ch++) + { + RETURN_IF(!lc3_enc_supported_lfe() && lfe_channel_array[ch], LC3PLUS_LFE_MODE_NOT_SUPPORTED); + } + +#ifdef ENABLE_HR_MODE + return FillEncSetup(encoder, samplerate, channels, hrmode + , lfe_channel_array + ); /* real bitrate check happens here */ +#else + return FillEncSetup(encoder, samplerate, channels + , lfe_channel_array + ); /* real bitrate check happens here */ +#endif +} + +int lc3plus_enc_get_size(int samplerate, int channels) +{ + RETURN_IF(!lc3plus_samplerate_supported(samplerate), 0); + RETURN_IF(!lc3plus_channels_supported(channels), 0); + return alloc_encoder(NULL, samplerate, channels); +} + +int lc3plus_enc_get_scratch_size(const LC3PLUS_Enc *encoder) +{ + int size = 0; + RETURN_IF(encoder == NULL, 0); + +#ifdef ENABLE_HR_MODE + size = 47 * MAX(encoder->frame_length, 160) + 64; +#else + size = 14 * MAX(encoder->frame_length, 160) + 64; +#endif + assert(size <= LC3PLUS_ENC_MAX_SCRATCH_SIZE); + return size; +} + +int lc3plus_enc_get_input_samples(const LC3PLUS_Enc *encoder) +{ + RETURN_IF(encoder == NULL, 0); + return encoder->frame_length; +} + +int lc3plus_enc_get_num_bytes(const LC3PLUS_Enc *encoder) +{ + RETURN_IF(encoder == NULL, 0); + return (Word32)encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in); +} + +int lc3plus_enc_get_real_bitrate(const LC3PLUS_Enc *encoder) +{ + int ch = 0, totalBytes = 0; + RETURN_IF(encoder == NULL, 0); + RETURN_IF(!encoder->lc3_br_set, LC3PLUS_BITRATE_UNSET_ERROR); + + for (ch = 0; ch < encoder->channels; ch++) + { + totalBytes += encoder->channel_setup[ch]->targetBytes; + } + + int bitrate = (totalBytes * 80000.0 + encoder->frame_dms - 1) / encoder->frame_dms; + + if (encoder->fs_in == 44100) + { + int rem = bitrate % 480; + bitrate = ((bitrate - rem) / 480) * 441 + (rem * 441) / 480; + } + + return bitrate; +} + +LC3PLUS_Error lc3plus_enc_set_bitrate(LC3PLUS_Enc *encoder, int bitrate) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(bitrate <= 0, LC3PLUS_BITRATE_ERROR); + return update_enc_bitrate(encoder, bitrate); +} + +int lc3plus_enc_get_delay(const LC3PLUS_Enc *encoder) +{ + RETURN_IF(encoder == NULL, 0); + return encoder->frame_length - 2 * encoder->la_zeroes; +} + +LC3PLUS_Error lc3plus_enc_set_ep_mode(LC3PLUS_Enc *encoder, LC3PLUS_EpMode epmode) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF((unsigned)epmode > LC3PLUS_EP_HIGH, LC3PLUS_EPMODE_ERROR); + encoder->epmode = epmode; + return encoder->lc3_br_set ? update_enc_bitrate(encoder, encoder->bitrate) : LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_enc_set_ep_mode_request(LC3PLUS_Enc *encoder, LC3PLUS_EpModeRequest epmr) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF((unsigned)epmr > LC3PLUS_EPMR_HIGH, LC3PLUS_EPMR_ERROR); + encoder->epmr = epmr; + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_dms) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(!lc3plus_frame_size_supported(frame_dms), LC3PLUS_FRAMEMS_ERROR); + RETURN_IF(encoder->lc3_br_set, LC3PLUS_BITRATE_SET_ERROR); + encoder->frame_dms = frame_dms; + set_enc_frame_params(encoder); + return LC3PLUS_OK; +} + + +LC3PLUS_Error lc3plus_enc_set_bandwidth(LC3PLUS_Enc *encoder, int bandwidth) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + Word32 effective_fs = encoder->fs_in; + if (encoder->bandwidth != bandwidth) { + if (encoder->fs_in > 40000) { + effective_fs = 40000; + } + if ((bandwidth * 2) > effective_fs) { + return LC3PLUS_BW_WARNING; + } + else { + encoder->bandwidth = bandwidth; + encoder->bandwidth_preset = bandwidth; + encoder->bw_ctrl_active = 1; + update_enc_bitrate(encoder, encoder->bitrate); + } + } + return LC3PLUS_OK; +} + + +static LC3PLUS_Error lc3plus_enc(LC3PLUS_Enc *encoder, void **input_samples, int bitdepth, void *output_bytes, int *num_bytes, + void *scratch) +{ + RETURN_IF(!encoder || !input_samples || !output_bytes || !num_bytes || !scratch, LC3PLUS_NULL_ERROR); + RETURN_IF(null_in_list(input_samples, encoder->channels), LC3PLUS_NULL_ERROR); + RETURN_IF(bitdepth != 16 && bitdepth != 24, LC3PLUS_ERROR); + RETURN_IF(!encoder->lc3_br_set, LC3PLUS_BITRATE_UNSET_ERROR); + *num_bytes = Enc_LC3PLUS(encoder, input_samples, bitdepth, output_bytes, scratch, *num_bytes == -1); + + assert(*num_bytes == lc3plus_enc_get_num_bytes(encoder)); + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_enc16(LC3PLUS_Enc *encoder, int16_t **input_samples, void *output_bytes, int *num_bytes, void *scratch) +{ + return lc3plus_enc(encoder, (void **)input_samples, 16, output_bytes, num_bytes, scratch); +} + +LC3PLUS_Error lc3plus_enc24(LC3PLUS_Enc *encoder, int32_t **input_samples, void *output_bytes, int *num_bytes, void *scratch) +{ + return lc3plus_enc(encoder, (void **)input_samples, 24, output_bytes, num_bytes, scratch); +} + +/* decoder functions *********************************************************/ + +LC3PLUS_Error lc3plus_dec_init(LC3PLUS_Dec *decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode +#ifdef ENABLE_HR_MODE + , int hrmode +#endif +) +{ + RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(!lc3plus_samplerate_supported(samplerate), LC3PLUS_SAMPLERATE_ERROR); + RETURN_IF(!lc3plus_channels_supported(channels), LC3PLUS_CHANNELS_ERROR); + RETURN_IF(!lc3plus_plc_mode_supported(plc_mode), LC3PLUS_PLCMODE_ERROR); +#ifdef ENABLE_HR_MODE + RETURN_IF(samplerate==96000 && hrmode == 0, LC3PLUS_HRMODE_ERROR); +#endif + + return FillDecSetup(decoder, samplerate, channels, plc_mode +#ifdef ENABLE_HR_MODE + , hrmode +#endif + ); +} + +int lc3plus_dec_get_size(int samplerate, int channels, LC3PLUS_PlcMode plc_mode) +{ + RETURN_IF(!lc3plus_samplerate_supported(samplerate), 0); + RETURN_IF(!lc3plus_channels_supported(channels), 0); + RETURN_IF(!lc3plus_plc_mode_supported(plc_mode), 0); + return alloc_decoder(NULL, samplerate, channels); +} + +int lc3plus_dec_get_scratch_size(const LC3PLUS_Dec *decoder) +{ + int size = 0; + RETURN_IF(decoder == NULL, 0); + +#ifdef ENABLE_HR_MODE + size = 30 * DYN_MAX_LEN(decoder->fs) + 2866; + size += 4 * MAX_LGW + 8 * DYN_MAX_LPROT(decoder->fs) + 16 * DYN_MAX_LEN(decoder->fs); +#else + size = 12 * DYN_MAX_LEN(decoder->fs) + 752; + size += 2 * MAX_LGW + 8 * DYN_MAX_LPROT(decoder->fs) + 8 * DYN_MAX_LEN(decoder->fs); + size += 3720; +#endif + + assert(size <= LC3PLUS_DEC_MAX_SCRATCH_SIZE); + return size; +} + +LC3PLUS_Error lc3plus_dec_set_ep_enabled(LC3PLUS_Dec *decoder, int ep_enabled) +{ + RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); + decoder->ep_enabled = ep_enabled != 0; + decoder->epmr = LC3PLUS_EPMR_ZERO; + return LC3PLUS_OK; +} + +int lc3plus_dec_get_error_report(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->error_report == 2047 ? -1 : decoder->error_report & 0x07FF; +} + +int lc3plus_dec_get_epok_flags(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->error_report >> 11; +} + +LC3PLUS_EpModeRequest lc3plus_dec_get_ep_mode_request(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, LC3PLUS_EPMR_ZERO); + return (LC3PLUS_EpModeRequest)decoder->epmr; +} + +LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_dms) +{ + RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(!lc3plus_frame_size_supported(frame_dms), LC3PLUS_FRAMEMS_ERROR); + RETURN_IF(decoder->plcMeth == 2 && frame_dms != 100, LC3PLUS_FRAMEMS_ERROR); + + decoder->frame_dms = frame_dms; + set_dec_frame_params(decoder); + return LC3PLUS_OK; +} + + +int lc3plus_dec_get_output_samples(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->frame_length; +} + +int lc3plus_dec_get_delay(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->frame_length - 2 * decoder->la_zeroes; +} + +static LC3PLUS_Error lc3plus_dec(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, void **output_samples, int bitdepth, + void *scratch, int bfi_ext) +{ + RETURN_IF(!decoder || !input_bytes || !output_samples || !scratch, LC3PLUS_NULL_ERROR); + RETURN_IF(null_in_list(output_samples, decoder->channels), LC3PLUS_NULL_ERROR); + RETURN_IF(bitdepth != 16 && bitdepth != 24, LC3PLUS_ERROR); + return Dec_LC3PLUS(decoder, input_bytes, num_bytes, output_samples, bitdepth, scratch, bfi_ext); +} + +LC3PLUS_Error lc3plus_dec16(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, int16_t **output_samples, void *scratch, int bfi_ext) +{ + return lc3plus_dec(decoder, input_bytes, num_bytes, (void **)output_samples, 16, scratch, bfi_ext); +} + +LC3PLUS_Error lc3plus_dec24(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, int32_t **output_samples, void *scratch, int bfi_ext) +{ + return lc3plus_dec(decoder, input_bytes, num_bytes, (void **)output_samples, 24, scratch, bfi_ext); +} diff --git a/lib_lc3plus/lc3.h b/lib_lc3plus/lc3.h new file mode 100644 index 000000000..64d8cc590 --- /dev/null +++ b/lib_lc3plus/lc3.h @@ -0,0 +1,520 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +/*! \file lc3.h + * This header provides the API for LC3plus. + * + * This library is targeting devices with extreme memory limitations, so memory management + * must be handeled by the user. This includes allocating memory for the structs and scratch + * memory. The structs are persistent between function calls. The scratch memory is working + * memory that does not persist between function calls. + * + * The amount of memory needed for various configurations can be obtained from the lc3plus_*_get_size + * and lc3plus_*_get_scratch_size functions. If memory usage is not a concern the LC3PLUS_*_MAX_SIZE + * LC3PLUS_*_MAX_SCRATCH_SIZE macros can be used for all configurations. + * + * Depending on the build configuration some functions might not be available. + */ + +#ifndef LC3PLUS_H +#define LC3PLUS_H + +#define ENABLE_HR_MODE + +#ifndef _MSC_VER +#include +#else +typedef __int16 int16_t; +typedef __int32 int32_t; +#endif + +/*! Construct version number from major/minor/micro values. */ +#define LC3PLUS_VERSION_INT(major, minor, micro) (((major) << 16) | ((minor) << 8) | (micro)) + +/*! Version number to ensure header and binary are matching. */ +#define LC3PLUS_VERSION LC3PLUS_VERSION_INT(1, 7, 3) + +/*! Maximum number of supported channels. The actual binary might support + * less, use lc3plus_channels_supported() to check. */ +#define LC3PLUS_MAX_CHANNELS 2 + +/*! Maximum number of samples per channel that can be stored in one LC3plus frame. */ +#ifdef ENABLE_HR_MODE +#define LC3PLUS_MAX_SAMPLES 960 +#else +#define LC3PLUS_MAX_SAMPLES 480 +#endif + +/*! Maximum number of bytes of one LC3plus frame. */ +#ifdef ENABLE_HR_MODE +#define LC3PLUS_MAX_BYTES (625 * LC3PLUS_MAX_CHANNELS) +#else +#define LC3PLUS_MAX_BYTES 870 +#endif + +/*! Maximum size needed to store encoder state. */ +#ifdef ENABLE_HR_MODE +#define LC3PLUS_ENC_MAX_SIZE 12628 +#else +#define LC3PLUS_ENC_MAX_SIZE 7226 +#endif + +/*! Maximum size needed to store decoder state. */ +#ifdef ENABLE_HR_MODE +#define LC3PLUS_DEC_MAX_SIZE 42488 +#else +#define LC3PLUS_DEC_MAX_SIZE 28446 +#endif + +/*! Maximum scratch size needed by lc3plus_enc16() or lc3plus_enc24().*/ +#ifdef ENABLE_HR_MODE +# define LC3PLUS_ENC_MAX_SCRATCH_SIZE 45624 +#else +# define LC3PLUS_ENC_MAX_SCRATCH_SIZE 6784 +#endif + +/*! Maximum scratch size needed by lc3plus_dec16() or lc3plus_dec24(). */ +#ifdef ENABLE_HR_MODE +#define LC3PLUS_DEC_MAX_SCRATCH_SIZE 59768 +#else +#define LC3PLUS_DEC_MAX_SCRATCH_SIZE 27474 +#endif +/*! Decoder packet loss concealment mode */ +typedef enum +{ + LC3PLUS_PLC_ADVANCED = 1 /*!< Enhanced concealment method */ +} LC3PLUS_PlcMode; + +/*! Error protection mode. LC3PLUS_EP_ZERO differs to LC3PLUS_EP_OFF in that + * errors can be detected but not corrected. */ +typedef enum +{ + LC3PLUS_EP_OFF = 0, /*!< Error protection is disabled */ + LC3PLUS_EP_ZERO = 1, /*!< Error protection with 0 bit correction */ + LC3PLUS_EP_LOW = 2, /*!< Error protection correcting one symbol per codeword */ + LC3PLUS_EP_MEDIUM = 3, /*!< Error protection correcting two symbols per codeword */ + LC3PLUS_EP_HIGH = 4 /*!< Error protection correcting three symbols per codeword */ +} LC3PLUS_EpMode; + +/*! Error protection mode request. On the encoder sidem, LC3PLUS_EPMR_ZERO to LC3PLUS_EPMR_HIGH + * can be set. The decoder returns mode requests with different confidences. */ +typedef enum +{ + LC3PLUS_EPMR_ZERO = 0, /*!< Request no error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_LOW = 1, /*!< Request low error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_MEDIUM = 2, /*!< Request medium error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_HIGH = 3, /*!< Request high error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_ZERO_MC = 4, /*!< No error correction requested, medium confidence. */ + LC3PLUS_EPMR_LOW_MC = 5, /*!< Low error correction requested, medium confidence. */ + LC3PLUS_EPMR_MEDIUM_MC = 6, /*!< Medium error correction requested, medium confidence. */ + LC3PLUS_EPMR_HIGH_MC = 7, /*!< High error correction requested, medium confidence. */ + LC3PLUS_EPMR_ZERO_NC = 8, /*!< No error correction requested, unvalidated. */ + LC3PLUS_EPMR_LOW_NC = 9, /*!< Low error correction requested, unvalidated. */ + LC3PLUS_EPMR_MEDIUM_NC = 10, /*!< Medium error correction requested, unvalidated. */ + LC3PLUS_EPMR_HIGH_NC = 11 /*!< High error correction requested, unvalidated. */ +} LC3PLUS_EpModeRequest; + +/*! Error codes returned by functions. */ +typedef enum +{ + LC3PLUS_OK = 0, /*!< No error occurred */ + LC3PLUS_ERROR = 1, /*!< Function call failed */ + LC3PLUS_DECODE_ERROR = 2, /*!< Frame failed to decode and was concealed */ + LC3PLUS_NULL_ERROR = 3, /*!< Pointer argument is null */ + LC3PLUS_SAMPLERATE_ERROR = 4, /*!< Invalid samplerate value */ + LC3PLUS_CHANNELS_ERROR = 5, /*!< Invalid channels value */ + LC3PLUS_BITRATE_ERROR = 6, /*!< Invalid bitrate value */ + LC3PLUS_NUMBYTES_ERROR = 7, /*!< Invalid num_bytes value */ + LC3PLUS_EPMODE_ERROR = 8, /*!< Invalid plc_method value */ + LC3PLUS_FRAMEMS_ERROR = 9, /*!< Invalid epmode value */ + LC3PLUS_ALIGN_ERROR = 10, /*!< Invalid frame_ms value */ + LC3PLUS_HRMODE_ERROR = 11, /*!< Unaligned pointer */ + LC3PLUS_BITRATE_UNSET_ERROR = 12, /*!< Invalid epmr value */ + LC3PLUS_BITRATE_SET_ERROR = 13, /*!< Invalid usage of hrmode, sampling rate and frame size */ + LC3PLUS_HRMODE_BW_ERROR = 14, /*!< Function called before bitrate has been set */ + LC3PLUS_PLCMODE_ERROR = 15, /*!< Function called after bitrate has been set */ + LC3PLUS_EPMR_ERROR = 16, /*!< Invalid external bad frame index */ + LC3PLUS_PADDING_ERROR = 17, /*!< Incorrect padding value */ + FRAMESIZE_ERROR = 18, /*!< Incorrect frame size during decoding */ + LC3PLUS_LFE_MODE_NOT_SUPPORTED = 19, /*!< LFE support not available */ + + /* START WARNING */ + LC3PLUS_WARNING = 20, + LC3PLUS_BW_WARNING = 21 /*!< Invalid bandwidth cutoff frequency */ + +} LC3PLUS_Error; + +typedef struct LC3PLUS_Enc LC3PLUS_Enc; /*!< Opaque encoder struct. */ +typedef struct LC3PLUS_Dec LC3PLUS_Dec; /*!< Opaque decoder struct. */ + +/*! \addtogroup Misc + * \{ */ + +/*! Test LFE mode support. + * + * Tests the support of the LFE mode. + * + * \return 1 for true, 0 for false. + */ +int32_t lc3_enc_supported_lfe(void); + +/*! Return library version number. It should match LC3PLUS_VERSION. */ +int lc3plus_version(void); + +/*! Tests if the library supports number of channels. + * + * \param[in] channels Number of channels. + * \return 1 for true, 0 for false. + */ +int lc3plus_channels_supported(int channels); + +/*! Tests if the library supports a sampling rate. + * + * \param[in] samplerate Sampling rate + * \return 1 for true, 0 for false + */ +int lc3plus_samplerate_supported(int samplerate); + +/*! \} + * \addtogroup Encoder + * \{ */ + +/*! + * Initialize LC3plus encoder. + * + * This function is used to fill a user-allocated encoder struct. This is typically + * called once for a samplerate / channel configuration. After init and before encoding + * the first frame you must call lc3plus_enc_set_bitrate(). + * + * \param[out] encoder Pointer to allocated encoder memory. It must have a size provided + * by lc3plus_enc_get_size() for matching samplerate / channels + * configuration or LC3PLUS_ENC_MAX_SIZE. + * \param[in] channels Number of channels. + * \param[in] samplerate Input sampling rate. Allowed sampling rates are: + * 8000, 16000, 24000, 32000, 44100, 48000 + * \param[in] hrmode High resolution mode. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_init(LC3PLUS_Enc *encoder, int samplerate, int channels +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + , int32_t lfe_channel_array[] + ); + +/*! + * Encode LC3plus frame with 16 bit input. + * + * Each call consumes a fixed number of samples. The number of input samples + * can be obtained from lc3plus_enc_get_input_samples(). + * + * \param[in] encoder Encoder handle initialized by lc3plus_enc_init(). + * \param[in] input_samples Input samples. The left channel is stored in input_samples[0], + * the right channel in input_samples[1]. The input is not changed + * by the encoder. + * \param[out] output_bytes Output buffer. It must have a at least lc3plus_enc_get_num_bytes() + * or at most LC3PLUS_MAX_BYTES. + * \param[out] num_bytes Number of bytes written to output_bytes. + * \param scratch A pointer to an allocated work buffer of at least + * lc3plus_enc_get_scratch_size() or at most LC3PLUS_ENC_SCRATCH_SIZE bytes. + * The buffer does not have to persist, so it can be used for other + * purposes in between calls. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc16(LC3PLUS_Enc *encoder, int16_t **input_samples, void *output_bytes, int *num_bytes, void *scratch); + +/*! Encode LC3plus frame with 24 bit input. + * + * The input samples are expected to be 24-bit values, sign-extended to 32-bit. + * See lc3plus_enc16() for parameter documentation. + */ +LC3PLUS_Error lc3plus_enc24(LC3PLUS_Enc *encoder, int32_t **input_samples, void *output_bytes, int *num_bytes, void *scratch); + +/*! Get the size of the LC3plus encoder struct for a samplerate / channel configuration. + * If memory is not restricted LC3PLUS_ENC_MAX_SIZE can be used for all configurations. + * + * \param[in] samplerate Sampling rate. + * \param[in] channels Number of channels. + * \return Size in bytes or 0 on error. + */ +int lc3plus_enc_get_size(int samplerate, int channels); + +/*! Get the size of the scratch buffer required by lc3plus_enc16() or lc3plus_enc24() for the current + * encoder configuration. If memory is not restricted, LC3PLUS_ENC_MAX_SCRATCH_SIZE can be used for + * all configurations. + * + * \param[in] encoder Encoder handle. + * \return Size in bytes or 0 on error. + */ +int lc3plus_enc_get_scratch_size(const LC3PLUS_Enc *encoder); + +/*! Get number of samples per channel expected by lc3plus_enc16() or lc3plus_enc24(). + * + * \param[in] encoder Encoder handle. + * \return Number of samples or 0 on error. + */ +int lc3plus_enc_get_input_samples(const LC3PLUS_Enc *encoder); + +/*! Get real internal bitrate of the encoder. It might differ from the requested bitrate due + * to error protection or 44.1 kHz input. + * + * \param[in] encoder Encoder handle. + * \return Bitrate in bits per second or 0 on error. + */ +int lc3plus_enc_get_real_bitrate(const LC3PLUS_Enc *encoder); + +/*! Get the maximum number of bytes produced by lc3plus_enc16() or lc3plus_enc24() for the current + * bitrate. It should be equal to the num_bytes output of lc3plus_enc16(). + * + * \param[in] encoder Encoder handle. + * \return Size in bytes or 0 on error. + */ +int lc3plus_enc_get_num_bytes(const LC3PLUS_Enc *encoder); + +/*! Set encoder bitrate for all channels. + * This function must be called at least once before encoding the first frame, but + * after other configuration functions such as lc3plus_enc_set_frame_dms(). + * + * Recommended bitrates for input sampling rates with 10 ms framing: + * kHz | kbps + * --------|----- + * 8 | 24 + * 16 | 32 + * 24 | 48 + * 32 | 64 + * 44.1/48 | 80(voice) 128(music) + * + * \param[in] encoder Encoder handle. + * \param[in] bitrate Bitrate in bits per second. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_bitrate(LC3PLUS_Enc *encoder, int bitrate); + +/*! Set encoder Low-frequency effect moded. deactivates LTPF, TNS, NF. + * + * \param[in] encoder Encoder handle. + * \param[in] lfe LFE mode flag + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_lfe(LC3PLUS_Enc* encoder, int lfe); + +/*! Get the encoder delay in number of samples. + * + * \param[in] encoder Encoder handle. + * \return Encoder in samples or 0 on error. + */ +int lc3plus_enc_get_delay(const LC3PLUS_Enc *encoder); + +/*! Set the frame length for LC3plus encoder in deci milliseconds. + * Not all lengths may be enabled, in that case LC3PLUS_FRAMEMS_ERROR is returned. + * This function must be called before lc3plus_enc_set_bitrate(). The decoder must be + * configured with lc3plus_dec_set_frame_dms() with the same value. + * + * \param[in] encoder Encoder handle. + * \param[in] frame_ms Frame length in ms. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_ms); + +/*! Set error protection mode. The default is LC3PLUS_EP_OFF. It is possible to switch between + * different modees during encoding. Dynamic switching is only allowed between LC3PLUS_EP_ZERO, + * LC3PLUS_EP_LOW, LC3_EP_MEDIUM, and LC3PLUS_EP_HIGH. The the decoder must be notified with + * lc3plus_dec_set_ep_enabled() to expect protected data if epmode is other than LC3PLUS_EP_OFF. + * + * \param[in] encoder Encoder handle. + * \param[in] epmode Error protection mode. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_ep_mode(LC3PLUS_Enc *encoder, LC3PLUS_EpMode epmode); + +/*! Sets error protection mode request transmitted in each channel encoded frame. + * The channel coder includes an error protection mode request (EPMR) in every frame. + * The EPMR takes value 0, 1, 2, and 3 which request ep modes 1, 2, 3, and 4 from the + * decoding device. The EPMR can be retrieved from the channel decoder via the interface + * routine lc3plus_dec_get_ep_mode_request(). + * + * \param[in] encoder Encoder handle. + * \param[in] epmr Error Protection Mode Request + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_ep_mode_request(LC3PLUS_Enc *encoder, LC3PLUS_EpModeRequest epmr); + +/*! Set encoder bandwidth to a different value. All frequency bins above the cutoff + * frequency are cut off. Allowed frequencies are: 4 kHz, 8 kHz, 12 kHz, 16 kHz and 24 kHz. + * + * \param[in] encoder Encoder handle. + * \param[in] bandwidth Cutoff Frequency in Hz + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_bandwidth(LC3PLUS_Enc *encoder, int bandwidth); + +/*! \} + * \addtogroup Decoder + * \{ */ + + +/*! + * Initialize LC3plus decoder. + * + * This function is used to fill a user-allocated decoder struct. This is typically + * called once for a samplerate / channel / plc_mode configuration. + * + * The samplerate and channel arguments must have the same values that were used for encoding. + * LC3plus does not provide a signalling scheme, transporting these values is the responsibility + * of the application. + * + * \param[out] decoder Pointer to decoder memory. It must have as size of least + * lc3plus_dec_get_size() or at most LC3PLUS_DEC_MAX_SIZE. + * \param[in] samplerate Bitstream sampling rate. + * \param[in] channels Bitstream number of channels. + * \param[in] plc_mode Packet loss concealment mode. + * \param[in] hrmode High resolution mode mode. + * + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_init(LC3PLUS_Dec *decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + ); + +/*! + * Decode compressed LC3plus frame to 16 bit PCM output. + * + * Each call decodes a fixed number of samples. Use lc3plus_dec_get_output_samples() to obtain this + * number. When the input is corrupted and can not be decoded, LC3PLUS_DECODE_ERROR is returned and + * packet loss concealment is applied, so the output is still usable. + * If error protection is enabled and the errors can be corrected the frame is corrected and + * normally decoded. Use lc3plus_dec_get_error_report() to check if errors were corrected. + * + * \param[in] decoder Decoder initialized by lc3plus_dec_init(). + * \param[in] input_bytes Input bytes. If error protection is enabled the input bytes can be + * altered when error correction is applied. This is why this buffer + * must be writable. + * \param[in] num_bytes Number of valid bytes in input_bytes. To signal a lost frame and + * generate concealment output this value must be set to 0. + * \param[out] output_samples Array of pointers to output channel buffers. Each channel buffer + * should provide enough space to hold at most LC3PLUS_MAX_SAMPLES. The + * left channel is stored in output_samples[0], the right channel in + * output_samples[1]. + * \param scratch A pointer to an allocated work buffer of at least + * lc3plus_dec_get_scratch_size() or at most LC3PLUS_DEC_MAX_SCRATCH_SIZE + * bytes. The scratch buffer does not have to persist, so it can be + * used for other purposes in between calls. + * \return Returns LC3PLUS_OK on success or appropriate error code. Note there is + * a special case for LC3PLUS_DECODE_ERROR where the output is still valid. + */ +LC3PLUS_Error lc3plus_dec16(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, int16_t **output_samples, void *scratch, + int bfi_ext); + +/*! Decode compressed LC3plus frame to 24 bit PCM output. + * + * The output samples are 24-bit values, sign-extended to 32-bit. + * See lc3plus_dec16() for parameter documentation. + */ +LC3PLUS_Error lc3plus_dec24(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, int32_t **output_samples, void *scratch, + int bfi_ext); + +/*! Get the size of the LC3plus decoder struct for a samplerate / channel / plc_mode configuration. + * If memory is not restricted LC3PLUS_DEC_MAX_SIZE can be used for all configurations. + * + * \param[in] channels Number of channels. + * \param[in] samplerate Sampling rate. + * \param[in] plc_mode Packet loss concealment mode. + * \return Size in bytes or 0 on error. + */ +int lc3plus_dec_get_size(int samplerate, int channels, LC3PLUS_PlcMode plc_mode); + +/*! Get the size of the scratch buffer required by lc3plus_dec16() or lc3plus_dec24() for the current + * decoder configuration. If memory is not restricted LC3PLUS_DEC_MAX_SCRATCH_SIZE can be used for + * all configurations. + * + * \param[in] decoder Decoder handle. + * \return Size in bytes or 0 on error. + */ +int lc3plus_dec_get_scratch_size(const LC3PLUS_Dec *decoder); + +/*! Get the number of samples per channel produced by lc3plus_dec16() or lc3plus_dec24(). + * + * \param[in] decoder Decoder handle. + * \return Number of samples or 0 on error. + */ + +int lc3plus_dec_get_output_samples(const LC3PLUS_Dec *decoder); + +/*! Get the decoder delay in number of samples. + * + * \param[in] decoder Decoder handle. + * \return Delay in samples or 0 on error. + */ +int lc3plus_dec_get_delay(const LC3PLUS_Dec *decoder); + +/*! Set the frame length for LC3plus decoder in deci milliseconds. + * Not all lengths may be enabled, in that case LC3PLUS_FRAMEMS_ERROR is returned. + * This only works correcly if the encoder was configured with the same vale. + * + * \param[in] decoder Decoder handle. + * \param[in] frame_ms Frame length in ms. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_ms); + +/*! Enable or disable error protection. Default value is 0 (disabled). If error protection is + * enabled, the decoder expects that the frames were encoded with error protection mode + * LC3PLUS_EP_ZERO or higher. + * + * \param[in] decoder Decoder handle. + * \param[in] ep_enabled 1 (or any nonzero) for true, 0 for false. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_set_ep_enabled(LC3PLUS_Dec *decoder, int ep_enabled); + +/*! Retrieves the error protection mode reqeust from channel decoder. + * + * The return value encodes both the error protection mode request (EPMR) + * and the confidence of the method by which it was retrieved. + * + * The requested error protection mode is (epmr % 4) + 1, where epmr is the + * function's return value. The confidence is specified as follows. + * + * Confidence | Range + * -----------|------------- + * high | 0 <= epmr < 4 + * medium | 4 <= epmr < 8 + * no | 8 <= epmr < 12 + * + * When receiving stereo content of separately channel encoded audio frames the + * return value is the minimum of two values retrieved from the individual channels. + * + * \param[in] decoder Decoder handle. + * \return Error protection mode reqeust. + */ +LC3PLUS_EpModeRequest lc3plus_dec_get_ep_mode_request(const LC3PLUS_Dec *decoder); + +/*! Get the number of corrected bit errors in the last decoded frame. This only works if + * error protection is active. If the number of errors is greater than the current error + * protection mode can correct, -1 is returned. If the last frame had no errors or the + * decoder handle is NULL, 0 is returned, + * + * \param[in] decoder Decoder handle. + * \return Number of corrected bits or -1. See description for details. + */ +int lc3plus_dec_get_error_report(const LC3PLUS_Dec *decoder); +/*! This function returns an set of flags indicating whether the last frame + * would have been channel decodable in epmode m, m ranging from 1 to 4. Note that + * this information is not available in case the last frame was not channel + * decodable in which case the return value is 0. If the last frame would have + * been decodable in epmode m, m-1th of the return value will be 1. + * Otherwise, if the frame would not have been decodable or if this information + * cannot be retrieved, the m-1th bit of the return value will be 0. + */ +int lc3plus_dec_get_epok_flags(const LC3PLUS_Dec *decoder); + +/*! \} */ +#endif /* LC3plus */ diff --git a/lib_lc3plus/levinson_fx.c b/lib_lc3plus/levinson_fx.c new file mode 100644 index 000000000..9003173d0 --- /dev/null +++ b/lib_lc3plus/levinson_fx.c @@ -0,0 +1,160 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processLevinson_fx(Word32 *lpc, Word32 *ac, Word16 N, Word16 *rc, Word32 *pred_err, Word8 *scratchBuffer) +{ + + Word32 *lpc_tmp; + Word32 rc32, err, sum; + Word16 shift, s, inv; + Counter n, m; + + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processLevinson_fx", sizeof(struct { + Word32 *lpc_tmp; + Word32 rc32, err, sum; + Word16 shift, s, inv; + Counter n, m; + Word32 params[2]; + })); +#endif + + lpc_tmp = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * (M_LTPF + 1) = 100 bytes */ + + /* Init Prediction Error */ + err = ac[0]; move32(); + shift = 0; move16(); + + /* LPC Coefficient 0 */ + lpc[0] = 0x8000000; move32(); + + /* Reflection Coefficient 0 */ + IF (ac[0] != 0) + { + inv = div_s(16383, extract_h(ac[0])); + rc32 = L_shl_pos(Mpy_32_32_lc3plus(L_abs(ac[1]), Mpy_32_16_lc3plus(L_sub(MAX_32, Mpy_32_16_lc3plus(ac[0], inv)), inv)), 2); + } + ELSE + { + rc32 = 0; move32(); + } + if (ac[1] > 0) + { + rc32 = L_negate(rc32); + } + if (rc != NULL) + { + rc[0] = round_fx(rc32); move16(); + } + + /* LPC Coefficient 1 */ + lpc[1] = L_shr_pos(rc32, 4); move32(); + + FOR (n = 2; n <= N; n++) + { + /* Update Prediction Error */ + err = Mpy_32_32_lc3plus(err, L_sub(MAX_32, Mpy_32_32_lc3plus(rc32, rc32))); + s = norm_l(err); + err = L_shl_pos(err, s); + shift = add(shift, s); + + /* Reflection Coefficient n-1 */ + sum = Mpy_32_32_lc3plus(ac[1], lpc[n - 1]); + FOR (m = 2; m < n; m++) + { + sum = L_add(sum, Mpy_32_32_lc3plus(ac[m], lpc[n - m])); + } + + sum = L_add(L_shl_pos(sum, 4), ac[n]); + IF (err != 0) + { + inv = div_s(16383, extract_h(err)); + rc32 = L_shl_pos(Mpy_32_32_lc3plus(L_abs(sum), Mpy_32_16_lc3plus(L_sub(MAX_32, Mpy_32_16_lc3plus(err, inv)), inv)), 2); + } + ELSE + { + rc32 = 0; + } + if (sum > 0) + { + rc32 = L_negate(rc32); + } + rc32 = L_shl(rc32, shift); + if (rc != NULL) + { + rc[n - 1] = round_fx(rc32); move16(); + } + +/* Recompute LPC Coefficients up to n-1 */ + FOR (m = 1; m < n; m++) + { + lpc_tmp[m] = L_add(lpc[m], Mpy_32_32_lc3plus(rc32, lpc[n - m])); move32(); + } + + basop_memmove(&lpc[1], &lpc_tmp[1], (n - 1) * sizeof(Word32)); + + /* LPC Coefficient n */ + lpc[n] = L_shr_pos(rc32, 4); move32(); + } + + /* Final Prediction Error */ + IF (pred_err != NULL) + { + err = Mpy_32_32_lc3plus(err, L_sub(MAX_32, Mpy_32_32_lc3plus(rc32, rc32))); + *pred_err = L_shr(err, shift); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + +void lpc2rc(Word32 *lpc, Word16 *rc, Word16 N) +{ + Word32 lpc_tmp[MAXLAG + 1]; + Word32 rc32, tmp0, tmp1; + Word16 inv; + Counter n, m; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("lpc2rc", sizeof(struct { + Word32 lpc_tmp[MAXLAG + 1]; + Word32 rc32, tmp0, tmp1; + Word16 inv; + Counter n, m; + })); +#endif + + FOR (n = N; n >= 2; n--) + { + rc32 = L_shl_pos(lpc[n], 4); + rc[n - 1] = round_fx(rc32); move16(); + + tmp0 = L_sub(MAX_32, L_abs(Mpy_32_32_lc3plus(rc32, rc32))); + FOR (m = 1; m < n; m++) + { + tmp1 = L_sub(lpc[m], Mpy_32_32_lc3plus(lpc[n - m], rc32)); + inv = div_s(16383, extract_h(tmp0)); + lpc_tmp[m] = L_shl_pos(Mpy_32_32_lc3plus(tmp1, Mpy_32_16_lc3plus(L_sub(MAX_32, Mpy_32_16_lc3plus(tmp0, inv)), inv)), 2); move32(); + } + + basop_memmove(&lpc[1], &lpc_tmp[1], (n - 1) * sizeof(Word32)); + } + + rc[0] = round_fx(L_shl_pos(lpc[1], 4)); move32(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/license.h b/lib_lc3plus/license.h new file mode 100644 index 000000000..22f25e9ff --- /dev/null +++ b/lib_lc3plus/license.h @@ -0,0 +1,21 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" + +static const char *const LICENSE = + "*******************************************************************************\n" + "* ETSI TS 103 634 V1.4.5 *\n" + "* Low Complexity Communication Codec Plus (LC3plus) *\n" + "* Fixed Point Software V%i.%i.%iETSI, " __DATE__ " *\n" + "* Copyright licence is solely granted through ETSI Intellectual Property *\n" + "* Rights Policy, 3rd April 2019. No patent licence is granted by implication, *\n" + "* estoppel or otherwise. *\n" + "*******************************************************************************\n" + "\n"; diff --git a/lib_lc3plus/ltpf_coder_fx.c b/lib_lc3plus/ltpf_coder_fx.c new file mode 100644 index 000000000..212788d73 --- /dev/null +++ b/lib_lc3plus/ltpf_coder_fx.c @@ -0,0 +1,323 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +/*************************************************************************/ + + +void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Word16 *mem_in_exp, Word16 mem_in[], + Word16 mem_in_len, Word16 param[], Word16 *xin, Word16 len, Word16 *mem_normcorr, + Word16 *mem_mem_normcorr, Word16 ol_normcorr, Word16 *mem_ltpf_on, Word16 *mem_ltpf_pitch, + Word16 xin_exp, Word16 frame_dms, Word8 *scratchBuffer +#ifdef CR9_K_REDUCE_NORM_CORR_TH + ,Word16 hrmode +#endif +) +{ + Word16 pitch_index, scale0, scale1, scale2, *x, x_exp, shift, prod_exp, ltpf_pitch; + Word32 L_tmp, cor_max32, sum0, sum1, sum2, prod, inv; + Word32 *ac32; + Word16 *ac, *currFrame, *predFrame; + Word16 min_pitch, max_pitch, ac_min_pitch, ac_max_pitch, ac_max; + Word16 pitch, pitch_res, min_pitch_fr, pitch_int, pitch_fr, norm_corr, ltpf_active; + Counter n, m, fr; + Word16 tmp, acflen; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("process_ltpf_coder_fx", sizeof(struct { + Word16 pitch_index, scale0, scale1, scale2, *x, x_exp, shift, prod_exp, ltpf_pitch; + Word32 L_tmp, cor_max32, sum0, sum1, sum2, prod, inv; + Word32 *ac32; + Word16 *ac, *currFrame, *predFrame; + Word16 min_pitch, max_pitch, ac_min_pitch, ac_max_pitch, ac_max; + Word16 pitch, pitch_res, min_pitch_fr, pitch_int, pitch_fr, norm_corr, ltpf_active; + Counter n, m, fr; + Word16 tmp, acflen; + })); +#endif + + + + ac32 = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * 17 = 68 bytes; */ + ac = (Word16 *)scratchAlign(ac32, sizeof(*ac32) * 17); /* Size = 2 * 17 = 34 bytes */ + currFrame = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * 128 = 256 bytes */ + predFrame = (Word16 *)scratchAlign(currFrame, sizeof(*currFrame) * LEN_12K8); /* Size = 2 * 128 = 256 bytes */ + /* Buffers 'overlap' since they are not used at the same time */ /* Total size used = 512 bytes */ + + ltpf_active = 0; move16(); + norm_corr = 0; move16(); + + /* Input buffer */ + x = mem_in + mem_in_len; + + basop_memmove(x, xin, (len + 1) * sizeof(Word16)); + + ASSERT(mem_in_len + len + 1 <= LTPF_MEMIN_LEN + LEN_12K8 + 1); + + /* Scaling */ + scale0 = sub(getScaleFactor16_0(mem_in, mem_in_len), 3); + *mem_in_exp = sub(*mem_in_exp, scale0); move16(); + scale1 = sub(getScaleFactor16_0(x, len + 1), 3); + x_exp = sub(xin_exp, scale1); + scale2 = sub(*mem_in_exp, x_exp); + IF (scale2 > 0) + { + Scale_sig(x, len + 1, sub(scale1, scale2)); + Scale_sig(mem_in, mem_in_len, scale0); + x_exp = *mem_in_exp; move16(); + } + ELSE + { + Scale_sig(x, len + 1, scale1); + Scale_sig(mem_in, mem_in_len, add(scale0, scale2)); + *mem_in_exp = x_exp; move16(); + } + +#ifdef CR9_K_REDUCE_NORM_CORR_TH + Word32 normCorrTh = 0; + if (hrmode) { + normCorrTh = 13107; + } else { + normCorrTh = 19660; + } +#endif + +#ifdef CR9_K_REDUCE_NORM_CORR_TH + IF (sub(ol_normcorr, normCorrTh) > 0) +#else + IF (sub(ol_normcorr, 19660) > 0) +#endif + { + /* Autocorrelation Bounds */ + min_pitch = sub(ol_pitch, 4); + max_pitch = add(ol_pitch, 4); + min_pitch = s_max(min_pitch, MIN_PITCH_12K8); + max_pitch = s_min(max_pitch, MAX_PITCH_12K8); + ac_min_pitch = sub(min_pitch, 4); + ac_max_pitch = add(max_pitch, 4); + acflen = len; move16(); + if (sub(frame_dms, 25) == 0) + { + acflen = shl(len, 1); + x = x - len; + } + + /* Compute norm */ + sum1 = L_mac0(1, x[0], x[0]); + sum2 = L_mac0(1, x[-ac_min_pitch], x[-ac_min_pitch]); + FOR (m = 1; m < acflen; m++) + { + sum1 = L_mac0(sum1, x[m], x[m]); + sum2 = L_mac0(sum2, x[m - ac_min_pitch], x[m - ac_min_pitch]); + } + scale1 = norm_l(sum1); + sum1 = L_shl_pos(sum1, scale1); + + /* Compute Autocorrelation */ + FOR (n = ac_min_pitch; n <= ac_max_pitch; n++) + { + sum0 = L_mac0(0L, x[0], x[0 - n]); + FOR (m = 1; m < acflen; m++) + { + sum0 = L_mac0(sum0, x[m], x[m - n]); + } + if (n > ac_min_pitch) + { + sum2 = L_msu0(sum2, x[acflen - 1 - (n - 1)], x[acflen - 1 - (n - 1)]); + sum2 = L_mac0_sat(sum2, x[-n], x[-n]); + } + scale2 = norm_l(sum2); + L_tmp = L_shl_pos(sum2, scale2); + prod = Mpy_32_32_lc3plus(sum1, L_tmp); + shift = norm_l(prod); + prod = L_shl_pos(prod, shift); + prod_exp = sub(62, add(add(scale1, scale2), shift)); + inv = Isqrt(prod, &prod_exp); + scale0 = norm_l(sum0); + sum0 = L_shl_pos(sum0, scale0); + prod = Mpy_32_32_lc3plus(sum0, inv); + prod_exp = add(sub(31, scale0), prod_exp); + test(); + IF (prod == 0 || sub(norm_l(prod), prod_exp) >= 0) + { + ac[n - ac_min_pitch] = s_max(0, round_fx_sat(L_shl_sat(prod, prod_exp))); move16(); + } + ELSE + { + ac[n - ac_min_pitch] = 32767; move16(); + } + } + + /* Find maximum */ + ac_max = ac[min_pitch - ac_min_pitch]; move16(); + pitch = min_pitch; move16(); + FOR (n = min_pitch + 1; n <= max_pitch; n++) + { + tmp = sub_sat(ac[n - ac_min_pitch], ac_max); + if (tmp > 0) + { + pitch = n; move16(); + } + ac_max = s_max(ac_max, ac[n - ac_min_pitch]); + } + pitch_int = pitch; move16(); + pitch_fr = 0; move16(); + pitch_index = add(pitch_int, 283); + + /* If the pitch is low -> estimate a fractional part */ + IF (sub(pitch, RES2_PITCH_12K8) < 0) + { + IF (sub(pitch, RES4_PITCH_12K8) < 0) + { + pitch_res = 1; move16(); + min_pitch_fr = -3; move16(); + } + ELSE + { + pitch_res = 2; move16(); + min_pitch_fr = -2; move16(); + } + if (sub(pitch, min_pitch) == 0) + { + min_pitch_fr = 0; + } + cor_max32 = MIN_32; + FOR (fr = min_pitch_fr; fr < 4; fr += pitch_res) + { + sum0 = L_mult0(ac[pitch_int - ac_min_pitch - 4], ltpf_ac_interp_filt[fr + 3][0]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch - 3], ltpf_ac_interp_filt[fr + 3][1]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch - 2], ltpf_ac_interp_filt[fr + 3][2]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch - 1], ltpf_ac_interp_filt[fr + 3][3]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch + 0], ltpf_ac_interp_filt[fr + 3][4]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch + 1], ltpf_ac_interp_filt[fr + 3][5]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch + 2], ltpf_ac_interp_filt[fr + 3][6]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch + 3], ltpf_ac_interp_filt[fr + 3][7]); + sum0 = L_mac0(sum0, ac[pitch_int - ac_min_pitch + 4], ltpf_ac_interp_filt[fr + 3][8]); + + L_tmp = L_sub_sat(sum0, cor_max32); + if (L_tmp > 0) + { + pitch_fr = fr; move16(); + } + cor_max32 = L_max(cor_max32, sum0); + } + IF (pitch_fr < 0) + { + pitch_int = sub(pitch_int, 1); + pitch_fr = add(pitch_fr, 4); + } + IF (sub(pitch_int, 127) >= 0) + { + pitch_index = add(add(shl_pos(pitch_int, 1), shr_pos(pitch_fr, 1)), 126); + } + ELSE + { + pitch_index = sub(add(shl_pos(pitch_int, 2), pitch_fr), 128); + } + } + ltpf_pitch = add(shl_pos(pitch_int, 2), pitch_fr); + + /* Filter current and predicted frame */ + + FOR (n = 0; n < acflen; n++) + { + sum0 = L_mult(x[n + 1], inter_filter[0][0][0]); + sum0 = L_mac(sum0, x[n], inter_filter[0][0][1]); + currFrame[n] = mac_r(sum0, x[n - 1], inter_filter[0][0][2]); + + sum0 = L_mult(x[n - pitch_int + 1], inter_filter[0][pitch_fr][0]); + sum0 = L_mac(sum0, x[n - pitch_int], inter_filter[0][pitch_fr][1]); + sum0 = L_mac(sum0, x[n - pitch_int - 1], inter_filter[0][pitch_fr][2]); + predFrame[n] = mac_r(sum0, x[n - pitch_int - 2], inter_filter[0][pitch_fr][3]); + } + + /* Normalized Correlation */ + sum0 = L_mult0(currFrame[0], predFrame[0]); + sum1 = L_mac0(1, predFrame[0], predFrame[0]); + sum2 = L_mac0(1, currFrame[0], currFrame[0]); + for (m = 1; m < acflen; m++) + { + sum0 = L_mac0(sum0, currFrame[m], predFrame[m]); + sum1 = L_mac0(sum1, predFrame[m], predFrame[m]); + sum2 = L_mac0(sum2, currFrame[m], currFrame[m]); + } + + scale1 = norm_l(sum1); + scale2 = norm_l(sum2); + sum1 = L_shl_pos(sum1, scale1); + sum2 = L_shl_pos(sum2, scale2); + prod = Mpy_32_32_lc3plus(sum1, sum2); + shift = norm_l(prod); + prod = L_shl_pos(prod, shift); + prod_exp = sub(62, add(add(scale1, scale2), shift)); + inv = Isqrt(prod, &prod_exp); + scale0 = norm_l(sum0); + sum0 = L_shl_pos(sum0, scale0); + prod = Mpy_32_32_lc3plus(sum0, inv); + prod_exp = add(sub(31, scale0), prod_exp); + test(); + IF (prod == 0 || sub(norm_l(prod), prod_exp) >= 0) + { + norm_corr = s_max(0, round_fx_sat(L_shl_sat(prod, prod_exp))); move16(); + } + ELSE + { + norm_corr = 32767; move16(); + } + if (norm_corr < 0) + { + norm_corr = 0; + } + + IF (sub(ltpf_enable, 1) == 0) + { + test(); test(); test(); test(); + /* Decision if lptf active */ + IF ((*mem_ltpf_on == 0 && sub(*mem_normcorr, 30802) > 0 && sub(norm_corr, 30802) > 0 && + (sub(frame_dms, 100) == 0 || sub(*mem_mem_normcorr, 30802) > 0)) || + (sub(*mem_ltpf_on, 1) == 0 && sub(norm_corr, 29491) > 0) || + (sub(*mem_ltpf_on, 1) == 0 && sub(abs_s(sub(ltpf_pitch, *mem_ltpf_pitch)), 8) < 0 && + add(sub(norm_corr, *mem_normcorr), 3277) > 0 && sub(norm_corr, 27525) > 0)) + { + ltpf_active = 1; move16(); + } + } + + param[0] = 1; move16(); + param[1] = ltpf_active; move16(); + param[2] = pitch_index; move16(); + *bits = 11; move16(); + } + ELSE + { + norm_corr = ol_normcorr; move16(); + param[0] = 0; move16(); + param[1] = 0; move16(); + param[2] = 0; move16(); + *bits = 1; move16(); + ltpf_pitch = 0; move16(); + } + +/* Update memory */ + FOR (n = 0; n < mem_in_len; n++) + { + mem_in[n] = mem_in[n + len]; move16(); + } + + *mem_mem_normcorr = *mem_normcorr; move16(); + *mem_normcorr = norm_corr; move16(); + *mem_ltpf_on = ltpf_active; move16(); + *mem_ltpf_pitch = ltpf_pitch; move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/ltpf_decoder_fx.c b/lib_lc3plus/ltpf_decoder_fx.c new file mode 100644 index 000000000..3bc82085e --- /dev/null +++ b/lib_lc3plus/ltpf_decoder_fx.c @@ -0,0 +1,394 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, Word16 pitch_int, Word16 pitch_fr, + Word16 gain, Word16 scale_fac_idx, Word16 fs_idx, + Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */); + +/*************************************************************************/ + + +void process_ltpf_decoder_fx(Word16 *x_e, Word16 L_frame, Word16 old_x_len, Word16 fs_idx, Word16 old_y_len, + Word16 *old_e, Word16 *x_in, Word16 *old_x, Word16 *y_out, Word16 *old_y, Word16 ltpf, + Word16 ltpf_active, Word16 pitch_index, Word16 *old_pitch_int, Word16 *old_pitch_fr, + Word16 *old_gain, Word16 *mem_ltpf_active, Word16 scale_fac_idx, Word16 bfi, + Word16 concealMethod, + Word16 damping, Word16 *old_scale_fac_idx, +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + Word32 *rel_pitch_change, Word16 hrmode, Word16 frame_dms, +#endif + Word8 *scratchBuffer) +{ + Counter i; + Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34; + Word16 *x, *y; + Word16 *z; +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + Word32 tmp32, pitch_delta; +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_In("process_ltpf_decoder_fx", sizeof(struct { + Counter i; + Word16 gain, s, s0, s1, pitch, pitch_int, pitch_fr, N4, N34; + Word16 *x, *y; + Word16 *z; +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + Word32 tmp32, pitch_delta; +#endif + })); +#endif + + z = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = MAX_LEN / 4 + 10 */ + + + test(); + IF ((sub(bfi, 1) == 0) && (sub(concealMethod, LC3_CON_TEC_NS_STD) == 0)) + { + ltpf = 0; move16(); + ltpf_active = 0; move16(); + pitch_int = 0; move16(); + pitch_fr = 0; move16(); + gain = 0; move16(); + } + + /* Filter parameters */ + IF (sub(bfi, 1) != 0) + { + IF (ltpf == 0) + { + pitch_int = 0; move16(); + pitch_fr = 0; move16(); + } + ELSE + { + /* Decode pitch */ + IF (sub(pitch_index, 380) < 0) + { + pitch_int = shr_pos(add(pitch_index, 64), 2); + pitch_fr = add(sub(pitch_index, shl_pos(pitch_int, 2)), 128); + } + ELSE IF (sub(pitch_index, 440) < 0) + { + pitch_int = shr_pos(sub(pitch_index, 126), 1); + pitch_fr = sub(sub(shl_pos(pitch_index, 1), shl_pos(pitch_int, 2)), 252); + } + ELSE + { + pitch_int = sub(pitch_index, 283); + pitch_fr = 0; move16(); + } + pitch = add(shl_pos(pitch_int, 2), pitch_fr); +#ifdef ENABLE_HR_MODE + IF (sub(fs_idx, 5) == 0) + { + pitch = round_fx(L_shl_pos(L_mult(shl_pos(pitch, 2), pitch_scale[4]), 1)); + } + ELSE +#endif + { + pitch = mult_r(shl_pos(pitch, 2), pitch_scale[fs_idx]); + } + pitch_int = shr_pos(pitch, 2); + pitch_fr = sub(pitch, shl_pos(pitch_int, 2)); + } + + /* Decode gain */ + if (scale_fac_idx < 0) + { + ltpf_active = 0; + ASSERT(!(*old_scale_fac_idx < 0 && *mem_ltpf_active == 1)); + } + IF (ltpf_active == 0) + { + gain = 0; move16(); + } + ELSE + { + ASSERT(scale_fac_idx >= 0); + gain = gain_scale_fac[scale_fac_idx]; move16(); + } + } + ELSE IF (sub(concealMethod, LC3_CON_TEC_NS_STD) != 0) + { + /* fix to avoid not initialized filtering for concelament + might be necessary in case of bit errors or rate switching */ + if (scale_fac_idx < 0) { + if (*mem_ltpf_active && *old_scale_fac_idx>=0) + { + scale_fac_idx = *old_scale_fac_idx; + } + } + + ltpf_active = *mem_ltpf_active; move16(); + + if ((sub(concealMethod, LC3_CON_TEC_PHASE_ECU) == 0)) + { /* always start fade off to save filtering WMOPS for the remaining 7.5 ms */ + assert(bfi == 1); + ltpf_active = 0; move16(); /*always start fade off , still maintain *mem_ltpf_active */ + } + + pitch_int = *old_pitch_int; + pitch_fr = *old_pitch_fr; + gain = mult_r(*old_gain, damping); + } + + test(); test(); + IF (ltpf_active == 0 && *mem_ltpf_active == 0) + { + /* LTPF inactive */ + + basop_memmove(y_out, x_in, L_frame * sizeof(Word16)); + + /* Update */ + s = sub(*old_e, *x_e); + IF (s > 0) + { + basop_memmove(old_y, &old_y[L_frame], (old_y_len - L_frame) * sizeof(Word16)); + + IF (sub(s, 15) > 0) + { + basop_memset(&old_y[old_y_len - L_frame], 0, (L_frame) * sizeof(Word16)); + + basop_memset(old_x, 0, (old_x_len) * sizeof(Word16)); + } + ELSE + { + FOR (i = 0; i < L_frame; i++) + { + old_y[i + old_y_len - L_frame] = shr(x_in[i], s); move16(); + } + FOR (i = 0; i < old_x_len; i++) + { + old_x[i] = shr(x_in[i + L_frame - old_x_len], s); move16(); + } + } + } + ELSE + { + IF (sub(s, -15) < 0) + { + basop_memset(old_y, 0, (old_y_len - L_frame) * sizeof(Word16)); + } + ELSE + { + FOR (i = 0; i < old_y_len - L_frame; i++) + { + old_y[i] = shl(old_y[i + L_frame], s); move16(); + } + } + + basop_memmove(&old_y[old_y_len - L_frame], x_in, (L_frame) * sizeof(Word16)); + + basop_memmove(old_x, &x_in[L_frame - old_x_len], (old_x_len) * sizeof(Word16)); + + *old_e = *x_e; move16(); + } + +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + if (bfi == 0 && sub(hrmode,1) == 0 && (sub(frame_dms,50) == 0 || sub(frame_dms,25) == 0)){ + pitch_delta = abs_s(add(sub(*old_pitch_int,pitch_int) , shr_pos(sub(*old_pitch_fr, pitch_fr),2))); //int_old -int_new + (fr_old-fr_new) / 4.0)); + tmp32 = BASOP_Util_Divide3216_Scale_lc3plus(pitch_delta, MAX(add(*old_pitch_int, shr_pos(*old_pitch_fr,2)), 1),&s0);// = pitch_delta *2^15 / MAX(pitch_fl_c_old, 1); + *rel_pitch_change = L_shl_pos(tmp32,s0+16); + } +#endif + + *old_pitch_int = pitch_int; move16(); + *old_pitch_fr = pitch_fr; move16(); + *old_gain = 0; move16(); + *mem_ltpf_active = 0; move16(); + } + ELSE + { + /* Input/Output buffers */ + x = old_x + old_x_len; + y = old_y + old_y_len; + +#ifdef ENABLE_HR_MODE + assert(fs_idx < 5 && "Ltpf not supported for 96kHz!\n"); +#endif + + N4 = ltpf_overlap_len[fs_idx]; move16(); + N34 = sub(L_frame, N4); move16(); + + /* Input */ + basop_memmove(x, x_in, (L_frame) * sizeof(Word16)); + + /* Scaling */ + s0 = sub(s_min(getScaleFactor16_0(old_x, old_x_len), getScaleFactor16_0(old_y, old_y_len)), 1); + *old_e = sub(*old_e, s0); move16(); + s1 = sub(getScaleFactor16(x, L_frame), 1); + *x_e = sub(*x_e, s1); move16(); + s = sub(*old_e, *x_e); + IF (s > 0) + { + Scale_sig(x, L_frame, sub(s1, s)); + Scale_sig(old_x, old_x_len, s0); + Scale_sig(old_y, old_y_len, s0); + *x_e = *old_e; move16(); + } + ELSE + { + Scale_sig(x, L_frame, s1); + Scale_sig(old_x, old_x_len, add(s0, s)); + Scale_sig(old_y, old_y_len, add(s0, s)); + *old_e = *x_e; move16(); + } + + /* Filtering */ + IF (ltpf_active == 0) + { + ltpf_synth_filter(y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx, + -1); + } + ELSE IF (*mem_ltpf_active == 0) + { + ltpf_synth_filter(y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 1); + } + ELSE IF (sub(pitch_int, *old_pitch_int) == 0 && sub(*old_pitch_fr, pitch_fr) == 0) + { + ltpf_synth_filter(y, x, N4, pitch_int, pitch_fr, gain, scale_fac_idx, fs_idx, 0); + } + ELSE + { + ltpf_synth_filter(y, x, N4, *old_pitch_int, *old_pitch_fr, *old_gain, *old_scale_fac_idx, fs_idx, + -1); + basop_memmove(z, y - tilt_filter_len[fs_idx], (N4 + tilt_filter_len[fs_idx]) * sizeof(Word16)); + ltpf_synth_filter(y, z + tilt_filter_len[fs_idx], N4, pitch_int, pitch_fr, gain, scale_fac_idx, + fs_idx, 1); + } + IF (ltpf_active > 0) + { + ltpf_synth_filter(y + N4, x + N4, N34, pitch_int, pitch_fr, gain, + scale_fac_idx, fs_idx, 0); + } + ELSE + { + basop_memmove(&y[N4], &x[N4], N34 * sizeof(Word16)); + } + + /* Output */ + basop_memmove(y_out, y, (L_frame) * sizeof(Word16)); + + /* Update */ + basop_memmove(old_x, &old_x[L_frame], (old_x_len) * sizeof(Word16)); + + basop_memmove(old_y, &old_y[L_frame], (old_y_len) * sizeof(Word16)); + + *old_pitch_int = pitch_int; move16(); + *old_pitch_fr = pitch_fr; move16(); + *old_gain = gain; move16(); + *mem_ltpf_active = ltpf_active; move16(); + } + + *old_scale_fac_idx = scale_fac_idx; move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + +static void ltpf_synth_filter(Word16 *synth_ltp, Word16 *synth, Word16 length, Word16 pitch_int, Word16 pitch_fr, + Word16 gain, Word16 scale_fac_idx, Word16 fs_idx, + Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */) +{ + Word16 *x0; + Word16 *y0; + Word32 s; + Word16 alpha, step; + Word16 i, k; + Counter j, l; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("ltpf_synth_filter", sizeof(struct { + Word16 *x0; + Word16 *y0; + Word32 s; + Word16 alpha, step; + Word16 i, k; + Counter j, l; + })); +#endif + + ASSERT(scale_fac_idx >= 0); + + step = 0; /* initialize just to avoid compiler warning */ + alpha = 0; /* initialize just to avoid compiler warning */ + x0 = &synth_ltp[-pitch_int + inter_filter_shift[fs_idx]]; + y0 = synth; + + alpha = 0; move16(); + IF (fade != 0) + { + if (fade < 0) + { + alpha = 0x7FFF; move16(); + } + +/* step = 1.f/(float)(length); */ + if (sub(length, 20) == 0) + { + step = 1638 /*1.f/20.f Q15*/; move16(); + } + if (sub(length, 40) == 0) + { + step = 819 /*1.f/40.f Q15*/; move16(); + } + if (sub(length, 60) == 0) + { + step = 546 /*1.f/60.f Q15*/; move16(); + } + if (sub(length, 80) == 0) + { + step = 409 /*1.f/80.f Q15*/; move16(); + } + if (sub(length, 120) == 0) + { + step = 273 /*1.f/120.f Q15*/; move16(); + } + + if (fade < 0) + step = negate(step); + } + + FOR (j = 0; j < length; j++) + { + s = L_mult(x0[0], inter_filter[fs_idx][pitch_fr][0]); + FOR (l = 1; l < inter_filter_len[fs_idx]; l++) + { + s = L_mac(s, x0[-l], inter_filter[fs_idx][pitch_fr][l]); + } + FOR (l = 0; l < tilt_filter_len[fs_idx]; l++) + { + s = L_msu(s, y0[-l], tilt_filter[fs_idx][scale_fac_idx][l]); + } + + i = msu_r(s, y0[-l], tilt_filter[fs_idx][scale_fac_idx][l]); + + k = mult_r(gain, i); + + if (fade != 0) + k = mult_r(k, alpha); + + synth_ltp[j] = add(synth[j], k); move16(); + + if (fade != 0) + alpha = add(alpha, step); + + x0++; + y0++; + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/makefile b/lib_lc3plus/makefile new file mode 100644 index 000000000..d86232d67 --- /dev/null +++ b/lib_lc3plus/makefile @@ -0,0 +1,180 @@ +#****************************************************************************** +# ETSI TS 103 634 V1.4.5 * +# Low Complexity Communication Codec Plus (LC3plus) * +# * +# Copyright licence is solely granted through ETSI Intellectual Property * +# Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +# estoppel or otherwise. * +#*****************************************************************************/ + +# Options +AFL = 0 +GCOV = 0 +NO_POST_REL_CHANGES_TEST = 0 +OPTIM = 0 +SUBSET = ALL +WMOPS = 1 +HR = 1 +CLANG = 0 +SHORT_PLC_FADEOUT = 0 + +# Paths +VPATH = . basic_op +BUILD = build +CC = gcc +LINK = $(CC) + +# Binary Name +NAME_LC3 = LC3plus +# Shared Library Name +LIB_LC3 = libLC3plus.so + +# Default tool settings +RM = rm -f + +ifndef VERBOSE +QUIET_CC = @echo ' ' Compiling $<; +QUIET_LINK= @echo ' ' Linking $@; +QUIET = @ +endif + +# C compiler flags +# Preprocessor(-I/-D) / Compiler / Linker flags +CPPFLAGS += -Ibasic_op -DSUBSET_$(SUBSET) +CFLAGS += -std=c99 -fPIC \ + -pedantic -Wcast-qual -Wall -W -Wextra -Wno-long-long \ + -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes \ + -Werror-implicit-function-declaration + +ifneq "$(DEBUG)" "0" +CFLAGS += -g3 +LDFLAGS += -g3 +endif + +ifeq "$(HR)" "0" +CFLAGS += -DDISABLE_HR_MODE +endif + +ifeq "$(SHORT_PLC_FADEOUT)" "1" +CFLAGS += -DPLC_TUNING_SHORT_FADEOUT +endif + +# memory sanitizer, find use of uninitialized memory +ifeq "$(CLANG)" "1" + CC = clang + CFLAGS += -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer + LDFLAGS += -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer + OPTIM = 2 +endif + +# address sanitizer, find buffer overflows +ifeq "$(CLANG)" "2" + CC = clang + CFLAGS += -fsanitize=address -fno-omit-frame-pointer + LDFLAGS += -fsanitize=address -fno-omit-frame-pointer + OPTIM = 2 +endif + +# undefined behavior sanitizer, find bugs like integer overflows +ifeq "$(CLANG)" "3" + CC = clang + CFLAGS += -fsanitize=undefined + LDFLAGS += -fsanitize=undefined + OPTIM = 2 +endif + +LDFLAGS += -lm + +DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD)/$*.Td + +ifeq "$(GCOV)" "1" +CFLAGS += -fprofile-arcs -ftest-coverage +LDFLAGS += -fprofile-arcs -ftest-coverage +endif + +OPTIM ?= 0 +CFLAGS += -O$(OPTIM) + +CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR)) + +ifeq "$(NO_POST_REL_CHANGES_TEST)" "1" +CFLAGS += -DNO_POST_REL_CHANGES +endif + +# disable wmops instrumentation +ifeq "$(WMOPS)" "0" + CPPFLAGS += -DWMOPS=0 -DDONT_COUNT_MEM +endif + +# dependency magic +CC_FLAGS = '$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)' +POSTCOMPILE = mv -f $(BUILD)/$*.Td $(BUILD)/$*.d && touch $@ + +############################################################################### + +SRCS := $(notdir $(foreach DIR, $(VPATH), $(wildcard $(DIR)/*.c))) + +EXCL := ccConvert.c +SRCS := $(notdir $(foreach DIR, $(VPATH), $(wildcard $(DIR)/*.c))) +SRCS := $(filter-out $(EXCL), $(SRCS)) + +EXCL_CCC := $(BUILD)/codec_exe.o +OBJS_CCC_UNF := $(addprefix $(BUILD)/, $(SRCS:.c=.o)) +OBJS_CCC := $(filter-out $(EXCL_CCC), $(OBJS_CCC_UNF)) + +OBJS := $(addprefix $(BUILD)/, $(SRCS:.c=.o)) + +LIBSRCS := $(filter-out $(DIR)/ccConvert.c $(DIR)/codec_exe.c, $(SRCS)) +LIBOBJS := $(addprefix $(BUILD)/, $(LIBSRCS:.c=.o)) + +############################################################################### + +.PHONY: all clean help force + +all: $(NAME_LC3) + +help: + @echo 'Targets:' + @echo ' $(NAME_LC3) (default)' + @echo ' $(LIB_LC3)' + @echo ' ccConvert' + @echo 'Syntax: make [OPTION=VALUE ...]' + @echo 'Build options:' + @echo ' NO_POST_REL_CHANGES_TEST $(NO_POST_REL_CHANGES_TEST) [0,1]' + @echo ' OPTIM $(OPTIM) [0-3]' + @echo ' SUBSET $(SUBSET) [NB,WB,SSWB,SWB,FB,UB,ALL]' + @echo ' WMOPS $(WMOPS) [0,1]' + @echo ' SHORT_PLC_FADEOUT $(SHORT_PLC_FADEOUT) [0,1]' + @echo 'Debug options:' + @echo ' AFL $(AFL) [0,1]' + @echo ' CLANG $(CLANG) [0-3]' + @echo ' GCOV $(GCOV) [0,1]' + +$(NAME_LC3): $(OBJS) + @echo 'Linking' $@ + $(QUIET) $(LINK) $(OBJS) -o $@ $(LDFLAGS) + +$(LIB_LC3): $(LIBOBJS) + @echo 'Linking' $@ + $(QUIET) $(LINK) --shared $(OBJS) -o $@ $(LDFLAGS) + +ccConvert: $(BUILD)/ccConvert.o $(OBJS_CCC) + @echo 'Linking' $@ + $(QUIET) $(LINK) $? -o $@ $(LDFLAGS) + +clean: + $(QUIET) rm -rf $(NAME_LC3) $(LIB_LC3) $(BUILD) ccConvert + +$(BUILD)/%.o : %.c $(BUILD)/cc_flags + @echo 'Compiling' $< + $(QUIET) $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< + $(QUIET) $(POSTCOMPILE) + +# force rebuild if compilation flags changed +$(BUILD)/cc_flags: force + $(QUIET) mkdir -p $(BUILD) + $(QUIET) echo $(CC_FLAGS) | cmp -s - $@ || echo $(CC_FLAGS) > $@ + +# force rebuild if include dependency changed +$(BUILD)/%.d: ; +include $(wildcard $(patsubst %, $(BUILD)/%.d, $(basename $(SRCS)))) diff --git a/lib_lc3plus/mdct_fx.c b/lib_lc3plus/mdct_fx.c new file mode 100644 index 000000000..9e9157204 --- /dev/null +++ b/lib_lc3plus/mdct_fx.c @@ -0,0 +1,223 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +/* Union holding buffers to conserve stack memory. */ + +void processMdct_fx( +#ifdef ENABLE_HR_MODE + Word32 x[], /* i: time input signal */ +#else + Word16 x[], /* i: time input signal */ +#endif + Word16 x_exp, Word16 N, /* i: block size N */ +#ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION +# ifdef ENABLE_HR_MODE + Word16 hrmode, /* i: indicate high precision */ +# endif +#endif +#ifdef ENABLE_HR_MODE + const Word32 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ +#else + const Word16 w[], /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ +#endif + Word16 wLen, /* i: window length */ +#ifdef ENABLE_HR_MODE + Word32 mem[], /* i/o: last block of input samples */ +#else + Word16 mem[], /* i/o: last block of input samples */ +#endif + Word16 memLen, /* i: length of last sample block */ + Word32 y[], /* o: spectral data */ + Word16 * y_e, /* o: spectal data exponent */ + Word8 * scratchBuffer) +{ + Counter i; + Word16 z, s, m; +#ifdef ENABLE_HR_MODE + Word32 *buf; +#else + Word16 *buf; +#endif + Word32 *workBuffer; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processMdct_fx", sizeof(struct { + Counter i; + Word16 z, s, m; + Word16 *buf; + Word32 *workBuffer; + })); +#endif + + /* Buffers overlap since they are not used at the same time */ +#ifdef ENABLE_HR_MODE + buf = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */ +#else + buf = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */ +#endif + workBuffer = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LEN */ + + /* Init (constant per sample rate) */ + z = (N << 1) - wLen; /* number of leading zeros in window */ + m = N >> 1; /* half block size */ + +#ifdef ENABLE_HR_MODE + basop_memmove(buf, mem, memLen * sizeof(Word32)); + + basop_memmove(&buf[memLen], x, (N - memLen) * sizeof(Word32)); + + basop_memmove(mem, &x[N - memLen], memLen * sizeof(Word32)); +#else + basop_memmove(buf, mem, memLen * sizeof(Word16)); + + basop_memmove(&buf[memLen], x, (N - memLen) * sizeof(Word16)); + + basop_memmove(mem, &x[N - memLen], memLen * sizeof(Word16)); +#endif + +#ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + +# ifdef ENABLE_HR_MODE + if (hrmode) + { + FOR (i = 0; i < m; i++) + { + y[m + i] = Msu_32_32_0(Mpy_32_32_0(w[i], buf[i]), w[2 * m - 1 - i], buf[2 * m - 1 - i]); move32(); + } + + FOR (i = 0; i < z; i++) + { + y[m - 1 - i] = Mpy_32_32_0(w[2 * m + i], x[2 * m - memLen + i]); move32(); + } + + FOR (i = i; i < m; i++) + { + y[m - 1 - i] = Mac_32_32_0(Mpy_32_32_0(w[2 * m + i], x[2 * m - memLen + i]), w[4 * m - 1 - i], x[4 * m - memLen - 1 - i]); move32(); + } + } else { +# ifdef CR9_B_FIX_MDCT_OVERFLOW + FOR (i = 0; i < m; i++) + { + y[m + i] = L_msu0(L_mult0(round_fx_sat(buf[i]), round_fx(w[i])), round_fx_sat(buf[2 * m - 1 - i]), round_fx(w[2 * m - 1 - i])); move32(); + } + + FOR (i = 0; i < z; i++) + { + y[m - 1 - i] = L_mult0(round_fx_sat(x[2 * m - memLen + i]), round_fx(w[2 * m + i])); move32(); + } + + FOR (i = i; i < m; i++) + { + y[m - 1 - i] = L_mac0(L_mult0(round_fx_sat(x[2 * m - memLen + i]), round_fx(w[2 * m + i])), round_fx_sat(x[4 * m - memLen - 1 - i]), + round_fx(w[4 * m - 1 - i])); move32(); + } +# else /* CR9_B_FIX_MDCT_OVERFLOW */ + FOR (i = 0; i < m; i++) + { + y[m + i] = L_msu0(L_mult0(round_fx(buf[i]), round_fx(w[i])), round_fx(buf[2 * m - 1 - i]), round_fx(w[2 * m - 1 - i])); move32(); + } + + FOR (i = 0; i < z; i++) + { + y[m - 1 - i] = L_mult0(round_fx(x[2 * m - memLen + i]), round_fx(w[2 * m + i])); move32(); + } + + FOR (i = i; i < m; i++) + { + y[m - 1 - i] = L_mac0(L_mult0(round_fx(x[2 * m - memLen + i]), round_fx(w[2 * m + i])), round_fx(x[4 * m - memLen - 1 - i]), + round_fx(w[4 * m - 1 - i])); move32(); + } +# endif /* CR9_B_FIX_MDCT_OVERFLOW */ + } +# else + /* regular resolution only */ + FOR (i = 0; i < m; i++) + { + y[m + i] = L_msu0(L_mult0(buf[i], w[i]), buf[2 * m - 1 - i], w[2 * m - 1 - i]); move32(); + } + + FOR (i = 0; i < z; i++) + { + y[m - 1 - i] = L_mult0(x[2 * m - memLen + i], w[2 * m + i]); move32(); + } + + FOR (i = i; i < m; i++) + { + y[m - 1 - i] = L_mac0(L_mult0(x[2 * m - memLen + i], w[2 * m + i]), x[4 * m - memLen - 1 - i], + w[4 * m - 1 - i]); move32(); + } +# endif + +#else /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + + FOR (i = 0; i < m; i++) + { +# ifdef ENABLE_HR_MODE + y[m + i] = Msu_32_32_0(Mpy_32_32_0(w[i], buf[i]), w[2 * m - 1 - i], buf[2 * m - 1 - i]); move32(); +# else + y[m + i] = L_msu0(L_mult0(buf[i], w[i]), buf[2 * m - 1 - i], w[2 * m - 1 - i]); move32(); +# endif + } + + FOR (i = 0; i < z; i++) + { +# ifdef ENABLE_HR_MODE + y[m - 1 - i] = Mpy_32_32_0(w[2 * m + i], x[2 * m - memLen + i]); move32(); +# else + y[m - 1 - i] = L_mult0(x[2 * m - memLen + i], w[2 * m + i]); move32(); +# endif + } + + FOR (i = i; i < m; i++) + { +# ifdef ENABLE_HR_MODE + y[m - 1 - i] = Mac_32_32_0(Mpy_32_32_0(w[2 * m + i], x[2 * m - memLen + i]), w[4 * m - 1 - i], x[4 * m - memLen - 1 - i]); move32(); +# else + y[m - 1 - i] = L_mac0(L_mult0(x[2 * m - memLen + i], w[2 * m + i]), x[4 * m - memLen - 1 - i], + w[4 * m - 1 - i]); move32(); +# endif + } + +#endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ + + s = s_max(0, getScaleFactor32_lc3plus(y, N)); + FOR (i = 0; i < N; i++) + { + y[i] = L_shl(y[i], s); move32(); + } + + *y_e = sub(sub(x_exp, 2), s); + + /* N=20 only for 2.5ms possible */ + /* maybe implement this a pre init of shift */ + if (sub(N, 20) <= 0) + { + *y_e = add(*y_e, 2); + } + else if (sub(N, 120) <= 0) + { + *y_e = add(*y_e, 1); + } +#ifdef ENABLE_HR_MODE + dct_IV(y, y_e, N, +# ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION + hrmode, +# endif + workBuffer); +#else + dct_IV(y, y_e, N, workBuffer); +#endif + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/mdct_shaping_fx.c b/lib_lc3plus/mdct_shaping_fx.c new file mode 100644 index 000000000..3b36265fd --- /dev/null +++ b/lib_lc3plus/mdct_shaping_fx.c @@ -0,0 +1,74 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processMdctShaping_fx(Word32 x[], +#ifdef ENABLE_HR_MODE + Word32 scf[], +#else + Word16 scf[], +#endif + Word16 scf_exp[], const Word16 bands_offset[], Word16 fdns_npts) +{ + Counter i, j; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processMdctShaping_fx", sizeof(struct { Counter i, j; })); +#endif + + j = 0; move16(); + FOR (i = 0; i < fdns_npts; i++) + { + FOR (; j < bands_offset[i + 1]; j++) + { +#ifdef ENABLE_HR_MODE + x[j] = L_shl(Mpy_32_32_lc3plus(x[j], scf[i]), scf_exp[i]); move32(); +#else + x[j] = L_shl(Mpy_32_16_lc3plus(x[j], scf[i]), scf_exp[i]); move32(); +#endif + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + +void processScfScaling(Word16 scf_exp[], Word16 fdns_npts, Word16 *x_e) +{ + Counter i; + Word16 scf_exp_max; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processLpcGainScaling", sizeof(struct { + Counter i; + Word16 scf_exp_max; + })); +#endif + + scf_exp_max = scf_exp[0]; move16(); + + FOR (i = 1; i < fdns_npts; i++) + { + scf_exp_max = s_max(scf_exp_max, scf_exp[i]); + } + + FOR (i = 0; i < fdns_npts; i++) + { + scf_exp[i] = sub(scf_exp[i], scf_exp_max); move16(); + } + + *x_e = add(*x_e, scf_exp_max); move16(); +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/near_nyquist_detector_fx.c b/lib_lc3plus/near_nyquist_detector_fx.c new file mode 100644 index 000000000..8ae29cbb8 --- /dev/null +++ b/lib_lc3plus/near_nyquist_detector_fx.c @@ -0,0 +1,141 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processNearNyquistdetector_fx(Word16 *near_nyquist_flag, const Word16 fs_idx, const Word16 near_nyquist_index, + const Word16 bands_number, const Word32 *ener_fx, const Word16 ener_fx_exp +#ifdef CR8_E_TONE_DETECTOR +#ifdef ENABLE_HR_MODE + ,Word16 frame_dms, Word16 hrmode) +#else + ) +#endif +#else + ) +#endif +{ + *near_nyquist_flag = 0; +#ifdef CR8_E_TONE_DETECTOR +#ifdef ENABLE_HR_MODE + IF (hrmode == 0){ +#endif +#endif + IF (sub(fs_idx, 4) < 0) + { + Dyn_Mem_Deluxe_In( + Word16 i; + Word16 nrg_above_thresh; + Word16 ener_low_exp; + Word16 ener_high_exp; + Word16 comp_energy_exp; + Word32 comp_energy; + Word32 ener_low; + Word32 ener_high; + ); + + ener_low = 0; move32(); + ener_low_exp = 0; move16(); + FOR (i = 0; i < near_nyquist_index; i++) + { + ener_low = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, ener_low, ener_low_exp, &ener_low_exp); + } + + ener_high = 0; move32(); + ener_high_exp = 0; move16(); + FOR (i = near_nyquist_index; i < bands_number; i++) + { + ener_high = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, ener_high, ener_high_exp, &ener_high_exp); + } + + comp_energy = Mpy_32_16_lc3plus(ener_low, NN_thresh); /* Mpy_32_16_lc3plus -> 32Q15 */ + comp_energy_exp = add(add(ener_low_exp, NN_thresh_exp),15); + + nrg_above_thresh = BASOP_Util_Cmp_Mant32Exp_lc3plus(ener_high, ener_high_exp, comp_energy, comp_energy_exp); /* 1 if firstNumber > secondNumber */ + + if (sub(nrg_above_thresh, 1) == 0) + { + *near_nyquist_flag = 1; + } + + Dyn_Mem_Deluxe_Out(); + } +#ifdef CR8_E_TONE_DETECTOR +#ifdef ENABLE_HR_MODE + } + ELSE // hrmode == 1 + { + // inverse spectral flatness = mean(energy) ./ 2^(mean(log2(energy))); + Word32 td_thresh; + + SWITCH (frame_dms) + { + case 25: + td_thresh = TD_HR_thresh_2_5ms; + BREAK; + case 50: + td_thresh = TD_HR_thresh_5ms; + BREAK; + #ifdef ENABLE_075_DMS_MODE + case 75: + td_thresh = TD_HR_thresh_7_5ms; + BREAK; + #endif + default: /* 100 */ + td_thresh = TD_HR_thresh_10ms; + BREAK; + } + + Word16 mean_ener_exp = 0; + + Word32 sum_ener = 0; move32(); + Word16 sum_ener_exp = 0; move16(); + FOR (Word16 i = 0; i < bands_number; i++) + { + sum_ener = BASOP_Util_Add_Mant32Exp_lc3plus(ener_fx[i], ener_fx_exp, sum_ener, sum_ener_exp, &sum_ener_exp); + } + + Word16 denom = sub(14,norm_s(bands_number)); + IF (sub(frame_dms, 50) == 0){ + denom = sub(15,norm_s(bands_number)); move16(); + } + + Word32 mean_ener = L_shr(sum_ener, denom); move32(); // = sum_ener / bands_number + mean_ener_exp = sum_ener_exp; move16(); + + Word32 sum_ener_log2 = 0;move32(); + Word16 sum_ener_log2_exp = 0;move16(); + Word32 mean_ener_log2 = 0;move32(); + + FOR (Word16 i = 0; i < bands_number; i++) + { + IF (ener_fx[i] != 0) { + Word32 log2Value = L_add(BASOP_Util_Log2_lc3plus(ener_fx[i]), L_shl_pos(L_deposit_l(ener_fx_exp), 25)); + /* input argument is in Q7.25 , returns pow(2,(x/64) + floatingpoint value log2_fl = log2Value/pow(2,31-6) */ + sum_ener_log2 = BASOP_Util_Add_Mant32Exp_lc3plus(log2Value, 6, sum_ener_log2, sum_ener_log2_exp, &sum_ener_log2_exp); move32(); + } + } + mean_ener_log2 = L_shr(sum_ener_log2, denom); move32(); //mean_ener_log2 = sum_ener_log2 / bands_number + Word16 mean_ener_log2_exp = sum_ener_log2_exp; + Word32 mean_ener_log2_fl = L_shr_pos(mean_ener_log2 ,s_min(31, sub(31,mean_ener_log2_exp))); //mean_ener_log2_fl = mean_ener_log2 / 2^(31-mean_ener_log2_exp) + Word32 inv_flatness = 0; + if (L_sub(norm_l(mean_ener),sub(sub(mean_ener_exp,31),mean_ener_log2_fl)) < 0 ) { + inv_flatness = maxWord32; + } + else { + inv_flatness = L_shl(mean_ener, s_max(-31,sub(sub(mean_ener_exp,31),mean_ener_log2_fl))); + } + IF (L_sub(inv_flatness, td_thresh) > 0) { + *near_nyquist_flag = 1; move16(); + } + } + #endif // ENABLE_HR_MODE +#endif // CR8_E_TONE_DETECTOR +} diff --git a/lib_lc3plus/noise_factor_fx.c b/lib_lc3plus/noise_factor_fx.c new file mode 100644 index 000000000..75ffb5fac --- /dev/null +++ b/lib_lc3plus/noise_factor_fx.c @@ -0,0 +1,252 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + + +void processNoiseFactor_fx(Word16 *fac_ns_idx, Word16 x_e, Word32 x[], +# ifdef ENABLE_HR_MODE + Word32 xq[], +# else + Word16 xq[], +# endif + Word16 gg, Word16 gg_e, Word16 BW_cutoff_idx, Word16 frame_dms, Word16 target_bytes, + Word8 *scratchBuffer +# ifdef ENABLE_HR_MODE + ,Word16 hrmode +# endif +) +{ + Dyn_Mem_Deluxe_In(Counter k; Word16 nzeros, s1, s2, s3, c, idx, fac_unq, *ind; + Word16 noisefillwidth, noisefillstart, N; Word32 Lsum;); + + + + ind = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN bytes */ + + noisefillwidth = 0; + noisefillstart = 0; + c = 0; + move16(); + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + N = BW_cutoff_bin_all_HR[BW_cutoff_idx]; + move16(); + } + else +#endif + { + N = BW_cutoff_bin_all[BW_cutoff_idx]; + move16(); + } + + SWITCH (frame_dms) + { + case 25: + N = shr_pos(N, 2); + noisefillwidth = NOISEFILLWIDTH_2_5MS; + noisefillstart = NOISEFILLSTART_2_5MS; + BREAK; + case 50: + N = shr_pos(N, 1); + noisefillwidth = NOISEFILLWIDTH_5MS; + noisefillstart = NOISEFILLSTART_5MS; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + N = add(shr_pos(N, 2), add(shr_pos(N, 2), shr_pos(N, 2))); + noisefillwidth = NOISEFILLWIDTH_7_5MS; + noisefillstart = NOISEFILLSTART_7_5MS; + BREAK; +# endif + case 100: + noisefillwidth = NOISEFILLWIDTH; + noisefillstart = NOISEFILLSTART; + BREAK; + } + + nzeros = -2 * noisefillwidth - 1; + move16(); + + FOR (k = noisefillstart - noisefillwidth; k < noisefillstart + noisefillwidth; k++) + { + if (xq[k] != 0) + { + nzeros = -2 * noisefillwidth - 1; + move16(); + } + if (xq[k] == 0) + { + nzeros = add(nzeros, 1); + } + } + + FOR (k = noisefillstart; k < N - noisefillwidth; k++) + { + if (xq[k + noisefillwidth] != 0) + { + nzeros = -2 * noisefillwidth - 1; + move16(); + } + if (xq[k + noisefillwidth] == 0) + { + nzeros = add(nzeros, 1); + } + if (nzeros >= 0) + { + ind[c++] = k; + move16(); + } + } + + FOR (k = N - noisefillwidth; k < N; k++) + { + nzeros = add(nzeros, 1); + if (nzeros >= 0) + { + ind[c++] = k; + move16(); + } + } + + IF (c == 0) + { + fac_unq = 0; + move16(); + } + ELSE + { + + IF (target_bytes <= 20 && frame_dms == 100) + { + Word32 ind_sum; + Word16 mean_ind; + + Word16 fac_unq1, fac_unq2; + + /* calculate mean index */ + ind_sum = ind[0]; + move32(); + FOR (k = 1; k < c; k++) + { + ind_sum = L_add(ind_sum, ind[k]); + } + + mean_ind = BASOP_Util_Divide3216_Scale_lc3plus(ind_sum, c, &s2); + mean_ind = shl(mean_ind, s2 + 1); + + assert(0 <= mean_ind && mean_ind <= ind[c - 1]); + + /* calculate noise filling gain for low frequencies */ + s2 = 0; move16(); + if (sub(mean_ind, ind[0]) > 0) + { + /* calculate scale to ensure that Lsum does not overflow */ + s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32_lc3plus(&x[ind[0]], sub(mean_ind, ind[0]))), 0); + } + Lsum = L_shr_pos_pos(L_abs(x[ind[0]]), s2); + + FOR (k = 1; k < c && ind[k] <= mean_ind; k++) + { + /* scale before adding to Lsum */ + Lsum = L_add(Lsum, L_shr_pos_pos(L_abs(x[ind[k]]), s2)); + } + fac_unq1 = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, k, &s1); + /* add scale applied during summing */ + s1 = add(s1, s2); + fac_unq1 = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq1, gg, &s2); + s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e)))); + s2 = norm_s(fac_unq1); + test(); + IF (fac_unq1 != 0 && add(s3, s2) < 0) + { + fac_unq1 = MAX_16; + move16(); + } + ELSE + { + s3 = s_min(s_max(s3, -15), 15); + fac_unq1 = shr_r(fac_unq1, s3); + } + + /* calculate noise filling gain for high frequencies */ + Lsum = 0; + move16(); + idx = sub(c, k); + FOR (; k < c; k++) + { + Lsum = L_add(Lsum, L_abs(x[ind[k]])); + } + fac_unq2 = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, idx, &s1); + fac_unq2 = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq2, gg, &s2); + s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e)))); + s2 = norm_s(fac_unq1); + test(); + IF (fac_unq2 != 0 && add(s3, s2) < 0) + { + fac_unq2 = MAX_16; + move16(); + } + ELSE + { + s3 = s_min(s_max(s3, -15), 15); + fac_unq2 = shr_r(fac_unq2, s3); + } + + /* calculate noise filling gain as minimum over high and low frequencies */ + fac_unq = s_min(fac_unq1, fac_unq2); + } + ELSE + { + /* calculate scale to ensure that Lsum does not overflow */ + s2 = s_max(sub(sub(14, norm_s(c)), getScaleFactor32_lc3plus(&x[ind[0]], sub(N,ind[0]))), 0); + Lsum = L_abs(x[ind[0]]); + FOR (k = 1; k < c; k++) + { + /* scale before adding to Lsum */ + Lsum = L_add(Lsum, L_shr_pos_pos(L_abs(x[ind[k]]), s2)); + } + fac_unq = BASOP_Util_Divide3216_Scale_lc3plus(Lsum, c, &s1); + /* add scale applied during summing */ + s1 = add(s1, s2); + fac_unq = BASOP_Util_Divide1616_Scale_lc3plus(fac_unq, gg, &s2); + s3 = sub(15, add(x_e, add(s1, sub(s2, gg_e)))); + s2 = norm_s(fac_unq); + test(); + IF (fac_unq != 0 && add(s3, s2) < 0) + { + fac_unq = MAX_16; + move16(); + } + ELSE + { + fac_unq = shr_r(fac_unq, s_max(s_min(s3, 15), -15)); + } + } + } + + idx = round_fx(L_sub(0x80000, L_mult(fac_unq, 16))); + if (sub(idx, 7) > 0) + { + idx = 7; + move16(); + } + if (idx < 0) + { + idx = 0; + move16(); + } + *fac_ns_idx = idx; + move16(); + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/noise_filling_fx.c b/lib_lc3plus/noise_filling_fx.c new file mode 100644 index 000000000..9da870553 --- /dev/null +++ b/lib_lc3plus/noise_filling_fx.c @@ -0,0 +1,149 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +/*************************************************************************/ + + + +void processNoiseFilling_fx(Word32 xq[], Word16 nfseed, Word16 xq_e, Word16 fac_ns_idx, Word16 BW_cutoff_idx, + Word16 frame_dms, Word16 fac_ns_pc, Word16 spec_inv_idx, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +) +{ + Dyn_Mem_Deluxe_In( + Counter k; + Word16 nzeros, fac_ns, *ind, c; + Word16 noisefillwidth, noisefillstart, N; + Word32 L_tmp, L_tmp_neg, L_tmp_pc, L_tmp_neg_pc; + ); + + ind = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN bytes */ + + c = 0; move16(); + +#ifdef ENABLE_HR_MODE + if (hrmode == 1) + { + N = BW_cutoff_bin_all_HR[BW_cutoff_idx]; + move16(); + } + else +#endif + { + N = BW_cutoff_bin_all[BW_cutoff_idx]; + move16(); + } + + SWITCH (frame_dms) + { + case 25: + N = shr_pos(N, 2); + noisefillwidth = NOISEFILLWIDTH_2_5MS; + noisefillstart = NOISEFILLSTART_2_5MS; + BREAK; + case 50: + N = shr_pos(N, 1); + noisefillwidth = NOISEFILLWIDTH_5MS; + noisefillstart = NOISEFILLSTART_5MS; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + N = add(shr_pos(N, 2), add(shr_pos(N, 2), shr_pos(N, 2))); + noisefillwidth = NOISEFILLWIDTH_7_5MS; + noisefillstart = NOISEFILLSTART_7_5MS; + BREAK; +#endif + default: /* 100 */ + noisefillwidth = NOISEFILLWIDTH; + noisefillstart = NOISEFILLSTART; + BREAK; + } + + nzeros = -2 * noisefillwidth - 1; move16(); + + FOR (k = noisefillstart - noisefillwidth; k < noisefillstart + noisefillwidth; k++) + { + if (xq[k] != 0) + { + nzeros = -2 * noisefillwidth - 1; move16(); + } + if (xq[k] == 0) + { + nzeros = add(nzeros, 1); + } + } + + FOR (k = noisefillstart; k < N - noisefillwidth; k++) + { + if (xq[k + noisefillwidth] != 0) + { + nzeros = -2 * noisefillwidth - 1; move16(); + } + if (xq[k + noisefillwidth] == 0) + { + nzeros = add(nzeros, 1); + } + if (nzeros >= 0) + { + ind[c++] = k; move16(); + } + } + + FOR (k = N - noisefillwidth; k < N; k++) + { + nzeros = add(nzeros, 1); + if (nzeros >= 0) + { + ind[c++] = k; move16(); + } + } + + IF (c > 0) + { + fac_ns = shl_pos(sub(8, fac_ns_idx), 11); + L_tmp = L_shr_sat(L_deposit_l(fac_ns), sub(xq_e, 16)); + L_tmp_neg = L_negate(L_tmp); + L_tmp_pc = L_shr_sat(L_deposit_l(fac_ns_pc), sub(xq_e, 16)); + L_tmp_neg_pc = L_negate(L_tmp_pc); + + FOR (k = 0; k < c; k++) + { + nfseed = extract_l(L_mac0(13849, nfseed, 31821)); + IF (nfseed >= 0) + { + IF (ind[k] < spec_inv_idx) + { + xq[ind[k]] = L_tmp; move32(); + } + ELSE + { + xq[ind[k]] = L_tmp_pc; move32(); + } + } + IF (nfseed < 0) + { + IF (ind[k] < spec_inv_idx) + { + xq[ind[k]] = L_tmp_neg; move32(); + } + ELSE + { + xq[ind[k]] = L_tmp_neg_pc; move32(); + } + } + } + } + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/olpa_fx.c b/lib_lc3plus/olpa_fx.c new file mode 100644 index 000000000..a72d8b61c --- /dev/null +++ b/lib_lc3plus/olpa_fx.c @@ -0,0 +1,289 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +/*************************************************************************/ + + +void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[], Word16 *pitch, Word16 *s12k8, + Word16 len, Word16 *normcorr, Word16 *mem_pitch, +#ifdef CR9_F_PITCH_WIN_LEN_FIX + Word16 *pitch_flag, +#endif + Word16 s12k8_exp, Word16 frame_dms, Word8 *scratchBuffer) +{ + Word32 sum, sum0, sum1, sum2, prod, inv; + Word16 shift, s6k4_exp, prod_exp, min_pitch, max_pitch; + Word16 scale0, scale1, scale2, pitch2, normcorr2, len2, acflen, mem_in_len; + Word32 max32; + Word32 *ac; + Word16 *s6k4; + Counter n; + + Counter m; + Word32 L_tmp, L_tmp2; + + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("process_olpa_fx", sizeof(struct { + Word32 sum, sum0, sum1, sum2, prod, inv; + Word16 shift, s6k4_exp, prod_exp, min_pitch, max_pitch; + Word16 scale0, scale1, scale2, pitch2, normcorr2, len2, acflen, mem_in_len; + Word32 max32; + Word32 *ac; + Word16 *s6k4; + Counter n; + Word32 sums[3]; + Counter m; + Word32 L_tmp, L_tmp2; + })); +#endif + + /* Buffer alignment */ + ac = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * RANGE_PITCH_6K4 = 392 bytes */ + + /* Downsample input signal by a factor of 2 (12.8kHz -> 6.4kHz) */ + mem_in_len = MAX_PITCH_6K4; move16(); + len2 = shr(len, 1); + acflen = len2; move16(); + +#ifdef CR9_F_PITCH_WIN_LEN_FIX + SWITCH(frame_dms) + { + case 50: + mem_in_len = add(mem_in_len, 32); + acflen = add(acflen, 32); + break; + + case 25: + mem_in_len = add(mem_in_len, 48); + acflen = add(acflen, 48); + break; + } +#endif + +#ifndef CR9_F_PITCH_WIN_LEN_FIX + IF (sub(frame_dms, 25) == 0) + { + mem_in_len = add(mem_in_len, 16); + acflen = add(acflen, 16); + } +#endif + + s6k4 = mem_s6k4 + mem_in_len; + sum = L_mac(L_mac(L_mult(mem_s12k8[0], 4053), mem_s12k8[1], 7712), mem_s12k8[2], 9239); + *s6k4++ = round_fx(L_mac_sat(L_mac(sum, s12k8[0], 7712), s12k8[1], 4053)); move16(); + sum = L_mac(L_mac(L_mult(mem_s12k8[2], 4053), s12k8[0], 7712), s12k8[1], 9239); + *s6k4++ = round_fx(L_mac_sat(L_mac(sum, s12k8[2], 7712), s12k8[3], 4053)); move16(); + + FOR (n = 5; n < len; n += 2) + { + sum = L_mac(L_mac(L_mult(s12k8[n - 4], 4053), s12k8[n - 3], 7712), s12k8[n - 2], 9239); + *s6k4++ = round_fx_sat(L_mac_sat(L_mac(sum, s12k8[n - 1], 7712), s12k8[n], 4053)); move16(); + } + + mem_s12k8[0] = s12k8[len - 3]; move16(); + mem_s12k8[1] = s12k8[len - 2]; move16(); + mem_s12k8[2] = s12k8[len - 1]; move16(); + + /* Scale downsampled signal */ + s6k4 = mem_s6k4 + mem_in_len; + scale0 = sub(getScaleFactor16_0(mem_s6k4, mem_in_len), 3); + *mem_s6k4_exp = sub(*mem_s6k4_exp, scale0); move16(); + scale1 = sub(getScaleFactor16_0(s6k4, len2), 3); + s6k4_exp = sub(s12k8_exp, scale1); + scale2 = sub(*mem_s6k4_exp, s6k4_exp); + IF (scale2 > 0) + { + Scale_sig(s6k4, len2, sub(scale1, scale2)); + shift = scale0; move16(); + s6k4_exp = *mem_s6k4_exp; move16(); + } + ELSE + { + Scale_sig(s6k4, len2, scale1); + shift = add(scale0, scale2); + *mem_s6k4_exp = s6k4_exp; move16(); + } +#ifdef CR9_F_PITCH_WIN_LEN_FIX + SWITCH(frame_dms) + { + case 50: + s6k4 = s6k4 - 32; + break; + + case 25: + s6k4 = s6k4 - 48; + break; + } +#endif + +#ifndef CR9_F_PITCH_WIN_LEN_FIX + if (sub(frame_dms, 25) == 0) + { + s6k4 = s6k4 - 16; + } +#endif + Scale_sig(mem_s6k4, mem_in_len, shift); + + /* Compute autocorrelation */ + FOR (n = MIN_PITCH_6K4; n <= MAX_PITCH_6K4; n++) + { + sum = L_mult0(s6k4[0], s6k4[0 - n]); + FOR (m = 1; m < acflen; m++) + { + sum = L_mac0(sum, s6k4[m], s6k4[m - n]); + } + ac[n - MIN_PITCH_6K4] = sum; move32(); + } + + /* Weight autocorrelation and find maximum */ + max32 = Mpy_32_16_lc3plus(ac[0], olpa_ac_weighting[0]); move32(); + *pitch = MIN_PITCH_6K4; move16(); + FOR (n = MIN_PITCH_6K4 + 1; n <= MAX_PITCH_6K4; n++) + { + L_tmp = Mpy_32_16_lc3plus(ac[n - MIN_PITCH_6K4], olpa_ac_weighting[n - MIN_PITCH_6K4]); + L_tmp2 = L_sub_sat(L_tmp, max32); + if (L_tmp2 > 0) + { + *pitch = n; move16(); + } + max32 = L_max(L_tmp, max32); + } + + /* Compute normalized correlation */ + sum0 = L_mult0(s6k4[0], s6k4[0 - *pitch]); + sum1 = L_mac0(1, s6k4[0 - *pitch], s6k4[0 - *pitch]); + sum2 = L_mac0(1, s6k4[0], s6k4[0]); + for (m = 1; m < acflen; m++) + { + sum0 = L_mac0(sum0, s6k4[m], s6k4[m - *pitch]); + sum1 = L_mac0(sum1, s6k4[m - *pitch], s6k4[m - *pitch]); + sum2 = L_mac0(sum2, s6k4[m], s6k4[m]); + } + scale1 = norm_l(sum1); + scale2 = norm_l(sum2); + sum1 = L_shl_pos(sum1, scale1); + sum2 = L_shl_pos(sum2, scale2); + prod = Mpy_32_32_lc3plus(sum1, sum2); + shift = norm_l(prod); + prod = L_shl_pos(prod, shift); + prod_exp = sub(62, add(add(scale1, scale2), shift)); + inv = Isqrt(prod, &prod_exp); + scale0 = norm_l(sum0); + sum0 = L_shl_pos(sum0, scale0); + prod = Mpy_32_32_lc3plus(sum0, inv); + prod_exp = add(sub(31, scale0), prod_exp); + test(); + IF (prod == 0 || sub(norm_l(prod), prod_exp) >= 0) + { + *normcorr = s_max(0, round_fx_sat(L_shl_sat(prod, prod_exp))); move16(); + } + ELSE + { + *normcorr = 32767; move16(); + } + + /* Second try in the neighborhood of the previous pitch */ + min_pitch = s_max(MIN_PITCH_6K4, sub(*mem_pitch, 4)); + max_pitch = s_min(MAX_PITCH_6K4, add(*mem_pitch, 4)); + + max32 = ac[min_pitch - MIN_PITCH_6K4]; move32(); + pitch2 = min_pitch; move16(); + FOR (n = min_pitch + 1; n <= max_pitch; n++) + { + L_tmp = L_sub_sat(ac[n - MIN_PITCH_6K4], max32); + if (L_tmp > 0) + { + pitch2 = n; move16(); + } + max32 = L_max(ac[n - MIN_PITCH_6K4], max32); + } + IF (sub(*pitch, pitch2) != 0) + { + sum0 = L_mult0(s6k4[0], s6k4[0 - pitch2]); + sum1 = L_mac0(1, s6k4[0 - pitch2], s6k4[0 - pitch2]); + sum2 = L_mac0(1, s6k4[0], s6k4[0]); + for (m = 1; m < acflen; m++) + { + sum0 = L_mac0(sum0, s6k4[m], s6k4[m - pitch2]); + sum1 = L_mac0(sum1, s6k4[m - pitch2], s6k4[m - pitch2]); + sum2 = L_mac0(sum2, s6k4[m], s6k4[m]); + } + scale1 = norm_l(sum1); + scale2 = norm_l(sum2); + sum1 = L_shl_pos(sum1, scale1); + sum2 = L_shl_pos(sum2, scale2); + prod = Mpy_32_32_lc3plus(sum1, sum2); + shift = norm_l(prod); + prod = L_shl_pos(prod, shift); + prod_exp = sub(62, add(add(scale1, scale2), shift)); + inv = Isqrt(prod, &prod_exp); + scale0 = norm_l(sum0); + sum0 = L_shl_pos(sum0, scale0); + prod = Mpy_32_32_lc3plus(sum0, inv); + prod_exp = add(sub(31, scale0), prod_exp); + test(); + IF (prod == 0 || sub(norm_l(prod), prod_exp) >= 0) + { + normcorr2 = s_max(0, round_fx_sat(L_shl_sat(prod, prod_exp))); move16(); + } + ELSE + { + normcorr2 = 32767; move16(); + } + IF (sub(normcorr2, mult_r(*normcorr, 27853)) > 0) + { + *pitch = pitch2; move16(); + *normcorr = normcorr2; move16(); + } + } + +#ifdef CR9_F_PITCH_WIN_LEN_FIX + SWITCH(frame_dms) + { + case 50: + if(*pitch_flag == 1) { + *mem_pitch = *pitch; move16(); + *pitch_flag = 0; + } + else { + *pitch_flag += 1; + } + break; + + case 25: + if (*pitch_flag == 3) { + *mem_pitch = *pitch; move16(); + *pitch_flag = 0; + } + else { + *pitch_flag += 1; + } + break; + + default: +#endif + *mem_pitch = *pitch; move16(); +#ifdef CR9_F_PITCH_WIN_LEN_FIX + } +#endif + + /* Update memory */ + basop_memmove(mem_s6k4, &mem_s6k4[len2], mem_in_len * sizeof(Word16)); + + /* Upsample pitch by a factor of 2 (6.4kHz -> 12.8kHz) */ + *pitch = shl_pos(*pitch, 1); move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/pc_apply_fx.c b/lib_lc3plus/pc_apply_fx.c new file mode 100644 index 000000000..42ddfb243 --- /dev/null +++ b/lib_lc3plus/pc_apply_fx.c @@ -0,0 +1,315 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "constants.h" +#include "functions.h" + +#ifdef ENABLE_HR_MODE +static Word16 getScaleFactor32_withNegativeScaling(Word32 *data32, Word16 dataLen); +#else +static Word16 getScaleFactor16_withNegativeScaling(Word16 *data16, Word16 dataLen); +#endif + + +void processPCapply_fx(Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp, +#ifdef ENABLE_HR_MODE + Word32 q_res_fx[], +#else + Word16 q_res_fx[], +#endif + Word16 q_old_d_fx[], Word16 spec_inv_idx, Word16 *fac, Word16 *fac_e, Word32 q_d_fx[], + Word16 *q_fx_exp, Word16 gg_idx, Word16 gg_idx_off, Word16 prev_gg, Word16 prev_gg_e, + Word16 *pc_nbLostFramesInRow) +{ + Counter i; + Word16 s, s2, s3, c, tmp16, tmp16_2, inv_gain, thr; + Word32 ener_curr, ener_prev, mean_nrg_high, mean_nrg_low; + Word16 global_gain, global_gain_e, gg2, gg2_e, prev_gg2, prev_gg2_e; + Word32 tmp32, ener_curr_gg2, ener_prev_gg2; + Word16 fac_local, fac_local_e; + +#ifdef DYNMEM_COUNT + struct _dynmem + { + Counter i; + Word16 s, s2, s3, c, tmp16, tmp16_2, inv_gain, thr; + Word32 ener_curr, ener_prev, mean_nrg_high, mean_nrg_low; + Word16 global_gain, global_gain_e, gg2, gg2_e, prev_gg2, prev_gg2_e; + Word32 tmp32, ener_curr_gg2, ener_prev_gg2; + Word16 fac_local, fac_local_e; + }; + Dyn_Mem_In("processPCapply_fx", sizeof(struct _dynmem)); +#endif + + assert(spec_inv_idx >= 0); + + *pc_nbLostFramesInRow = add(*pc_nbLostFramesInRow, 1); + + tmp32 = L_shl_pos(L_mult0(add(gg_idx, gg_idx_off), 0x797D), 7); + global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); + global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); + + /** Calculate rescaling factor **/ + + /* mean_nrg_low = mean(q_d_prev(1:spec_inv_idx-1).^2); + mean_nrg_high = mean(q_d_prev(spec_inv_idx:end).^2); */ + s = getScaleFactor16(q_old_d_fx, yLen); + + mean_nrg_low = 0; + move32(); + FOR (i = 0; i < spec_inv_idx; i++) + { + tmp16 = shl_sat(q_old_d_fx[i], sub(s, 4)); + mean_nrg_low = L_mac0(mean_nrg_low, tmp16, tmp16); /* exp = 2s - 8 */ + } + + mean_nrg_high = 0; + move32(); + FOR (i = spec_inv_idx; i < yLen; i++) + { + tmp16 = shl_sat(q_old_d_fx[i], sub(s, 4)); + mean_nrg_high = L_mac0(mean_nrg_high, tmp16, tmp16); /* exp = 2s - 8 */ + } + + IF (sub(spec_inv_idx, sub(yLen, spec_inv_idx)) < 0) + { + c = div_s(spec_inv_idx, sub(yLen, spec_inv_idx)); + mean_nrg_high = Mpy_32_16_lc3plus(mean_nrg_high, c); /* exp = 2s - 8 */ + } + ELSE + { + c = div_s(sub(yLen, spec_inv_idx), spec_inv_idx); + mean_nrg_low = Mpy_32_16_lc3plus(mean_nrg_low, c); /* exp = 2s - 8 */ + } + + /* ener_prev = sum(q_old_res(1:spec_inv_idx-1).^2); + ener_curr = sum( q_res(1:spec_inv_idx-1).^2); */ + s = getScaleFactor16(q_old_res_fx, spec_inv_idx); + ener_prev = 0; move32(); + FOR (i = 0; i < spec_inv_idx; i++) + { + tmp16 = shl_sat(q_old_res_fx[i], sub(s, 4)); + ener_prev = L_mac0(ener_prev, tmp16, tmp16); /* exp = - (2s - 8 - 2**q_old_res_fx_exp) */ + } + + ener_curr = 0; + move32(); + +#ifdef ENABLE_HR_MODE + s2 = getScaleFactor32_lc3plus(q_res_fx, spec_inv_idx); + FOR (i = 0; i < spec_inv_idx; i++) + { + tmp16 = extract_h(L_shl_sat(q_res_fx[i], sub(s2, 4))); + ener_curr = L_mac0(ener_curr, tmp16, tmp16); /* exp = - (2s2 - 8) */ + } + s2 = s2 - 16; +#else + s2 = getScaleFactor16(q_res_fx, spec_inv_idx); + FOR (i = 0; i < spec_inv_idx; i++) + { + tmp16 = shl_sat(q_res_fx[i], sub(s2, 4)); + ener_curr = L_mac0(ener_curr, tmp16, tmp16); /* exp = - (2s2 - 8) */ + } +#endif + + + s = shl(sub(s, *q_old_res_fx_exp), 1); + s2 = shl(s2, 1); + s3 = s_max(s, s2); + ener_prev = L_shr_sat(ener_prev, sub(s3, s2)); + ener_curr = L_shr_sat(ener_curr, sub(s3, s)); + + /* fac = 1; */ + *fac = 1; + /* if ener_prev > 0 */ + IF ( ener_prev > 0 ) + { + /* fac = sqrt(ener_curr/ener_prev); */ + s = getScaleFactor32_lc3plus(&ener_prev, 1); + s2 = getScaleFactor32_lc3plus(&ener_curr, 1); + s3 = s_min(s, s2); + tmp16 = extract_h(L_shl_sat(ener_curr, s3)); + tmp16_2 = extract_h(L_shl_sat(ener_prev, s3)); + + *fac_e = 0; move16(); + if ( tmp16_2 == 0) { + tmp16_2 = 32767; move16(); + *fac_e = 15; move16(); + } else { + tmp16_2 = Inv16_lc3plus(tmp16_2, fac_e); + } + + *fac = mult(tmp16, tmp16_2); + + IF (sub(*fac, 32767) < 0) + { + *fac = Sqrt16_lc3plus(*fac, fac_e); move16(); + } + } + + /* fac_local = fac; */ + fac_local = *fac; + fac_local_e = *fac_e; + + /* if (mean_nrg_low > mean_nrg_high) && (ener_prev * prev_gg^2 > ener_curr * gg^2) */ + prev_gg2 = mult(prev_gg, prev_gg); + prev_gg2_e = shl(prev_gg_e, 1); + ener_prev_gg2 = Mpy_32_16_lc3plus(ener_prev, prev_gg2); /* exp = prev_gg2_e */ + + gg2 = mult(global_gain, global_gain); + gg2_e = shl(global_gain_e, 1); + ener_curr_gg2 = Mpy_32_16_lc3plus(ener_curr, gg2); /* exp = gg2_e */ + + s3 = s_max(prev_gg2_e, gg2_e); + ener_prev_gg2 = L_shr_sat(ener_prev_gg2, sub(s3, prev_gg2_e)); + ener_curr_gg2 = L_shr_sat(ener_curr_gg2, sub(s3, gg2_e)); + + + test(); + IF ( (L_sub(mean_nrg_low, mean_nrg_high) <= 0) || (L_sub(ener_prev_gg2, ener_curr_gg2) <= 0) ) + { + /* fac = prev_gg/gg; */ + s = global_gain_e; move16(); + inv_gain = Inv16_lc3plus(global_gain, &s); + fac_local = mult(prev_gg, inv_gain); + fac_local_e = add(s, prev_gg_e); + } + + /* write synthesized samples */ + *q_old_res_fx_exp = add(*q_old_res_fx_exp, fac_local_e); + thr = shl_sat(20480, sub(-15, *q_old_res_fx_exp)); + FOR (i = spec_inv_idx; i < yLen; i++) + { + q_res_fx[i] = extract_h(L_mult(q_old_res_fx[i] /* exp = q_old_res_fx_exp' */, fac_local /* exp = fac_e */)); /* exp = q_old_res_fx_exp */ + + IF (sub(abs_s(q_res_fx[i]), thr) < 0) + { + q_res_fx[i] = 0; + move16(); + } + } + +#ifdef ENABLE_HR_MODE + s = getScaleFactor32_withNegativeScaling(&q_res_fx[0], spec_inv_idx) - 16; /* exp = 0 */ + s2 = getScaleFactor32_withNegativeScaling(&q_res_fx[spec_inv_idx], + sub(yLen, spec_inv_idx)) - 16; /* exp = q_old_res_fx_exp */ +#else + s = getScaleFactor16_withNegativeScaling(&q_res_fx[0], spec_inv_idx); /* exp = 0 */ + s2 = getScaleFactor16_withNegativeScaling(&q_res_fx[spec_inv_idx], + sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */ +#endif + + s3 = add(s, *q_old_res_fx_exp); + IF (sub(s3, s2) > 0) + { + tmp16 = sub(s3, s2); + s = sub(s, tmp16); + s3 = sub(s3, tmp16); + } + *q_fx_exp = sub(15, s); + move16(); + +#ifdef ENABLE_HR_MODE + s = add(s, 16); + s3 = add(s3, 16); +#endif + + s = s_max(s, -31); + s = s_min(s, 31); + s3 = s_max(s3, -31); + s3 = s_min(s3, 31); + + FOR (i = 0; i < spec_inv_idx; i++) + { +#ifdef ENABLE_HR_MODE + q_d_fx[i] = L_shl(q_res_fx[i], s); +#else + q_d_fx[i] = L_shl(L_deposit_h(q_res_fx[i]), s); +#endif + move32(); + } + FOR (; i < yLen; i++) + { +#ifdef ENABLE_HR_MODE + q_d_fx[i] = L_shl(q_res_fx[i], s3); +#else + q_d_fx[i] = L_shl(L_deposit_h(q_res_fx[i]), s3); +#endif + move32(); + } + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +#ifndef ENABLE_HR_MODE +static Word16 getScaleFactor16_withNegativeScaling(Word16 *data16, Word16 dataLen) +{ + Counter i; + Dyn_Mem_Deluxe_In(Word16 tmp, shift; Word16 x_min, x_max;); + + x_max = 0; + move16(); + x_min = 0; + move16(); + + FOR (i = 0; i < dataLen; i++) + { + if (data16[i] > 0) + x_max = s_max(x_max, data16[i]); + if (data16[i] < 0) + x_min = s_min(x_min, data16[i]); + } + + tmp = s_max(x_max, negate(x_min)); + shift = norm_s(tmp); + if (tmp == 0) + { + shift = 15; + move16(); + } + + Dyn_Mem_Deluxe_Out(); + + return shift; +} + +#else +static Word16 getScaleFactor32_withNegativeScaling(Word32 *data32, Word16 dataLen) +{ + Counter i; + Dyn_Mem_Deluxe_In(Word32 tmp, shift; Word32 x_min, x_max;); + + x_max = L_add(0, 0); + x_min = L_add(0, 0); + + FOR (i = 0; i < dataLen; i++) + { + if (data32[i] >= 0) + x_max = L_max(x_max, data32[i]); + if (data32[i] < 0) + x_min = L_min(x_min, data32[i]); + } + + tmp = L_max(x_max, L_negate(x_min)); + shift = norm_l(tmp); + if (tmp == 0) + { + shift = 31; + move16(); + } + + Dyn_Mem_Deluxe_Out(); + + return shift; +} +#endif diff --git a/lib_lc3plus/pc_classify_fx.c b/lib_lc3plus/pc_classify_fx.c new file mode 100644 index 000000000..28898f963 --- /dev/null +++ b/lib_lc3plus/pc_classify_fx.c @@ -0,0 +1,260 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "constants.h" +#include "functions.h" + +#define BLOCK_SIZE 3 +#define THR1 8 +#define FAC 9830 /* 0.3 */ + +void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover); + +void processPCclassify_fx(Word16 pitch_present, Word16 frame_dms, Word16 q_old_d_fx[], Word16 q_old_res_fx[], + Word16 yLen, Word16 spec_inv_idx, Word16 stab_fac, Word16 *bfi) +{ + Dyn_Mem_Deluxe_In( + Word16 maxPitchBin, xover; + Counter i; + Word16 s, tmp16, full_nrg16, part_nrg16; + Word32 full_nrg, part_nrg; + ); + + /* Apply classifier only if lower than 2kHz signal */ + IF (sub(DEPR_i_mult(spec_inv_idx, 10), shl_pos(frame_dms, 2)) < 0 ) + { + IF (sub(stab_fac, 16384 /* 0.5 */) < 0) + { + *bfi = 1; + } + ELSE IF (sub(pitch_present, 1) == 0) + { + maxPitchBin = 8; move16(); + IF (sub(frame_dms, 50) == 0) + { + maxPitchBin = 4; move16(); + } + + /* avoid phase discontinuity in low frequencies */ + peakDetector_fx(q_old_d_fx, yLen, &xover); + test(); + IF (sub(spec_inv_idx, xover) < 0 || sub(spec_inv_idx, maxPitchBin) < 0) + { + *bfi = 1; + } + } + ELSE + { + s = getScaleFactor16(q_old_res_fx, yLen); + + part_nrg = 0; move32(); + FOR (i = 0; i < spec_inv_idx; i++) + { + tmp16 = shl_sat(q_old_res_fx[i], sub(s, 4)); + part_nrg = L_mac0(part_nrg, tmp16, tmp16); /* exp = 2s - 8 */ + } + + full_nrg = part_nrg; move32(); + FOR (i = spec_inv_idx; i < yLen; i++) + { + tmp16 = shl_sat(q_old_res_fx[i], sub(s, 4)); + full_nrg = L_mac0(full_nrg, tmp16, tmp16); /* exp = 2s - 8 */ + } + + s = getScaleFactor32_lc3plus(&full_nrg, 1); + full_nrg16 = extract_h(L_shl(full_nrg, s)); + part_nrg16 = extract_h(L_shl(part_nrg, s)); + + tmp16 = mult(full_nrg16, 9830 /* 0.3 */); + + IF (part_nrg16 < tmp16) + { + *bfi = 1; + } + } + } + + Dyn_Mem_Deluxe_Out(); +} + +void peakDetector_fx(Word16 in_sig[], Word16 yLen, Word16 *xover) +{ + Dyn_Mem_Deluxe_In( + Counter i, j; + Word16 tmp16, c, s, s2, mean_block_nrg16; + Word32 maxPeak, tmp32; + Word32 mean_block_nrg, block_cent; + Word16 cur_max, prev_max, next_max; + ); + + *xover = 0; + + s = getScaleFactor16(in_sig, yLen); + + mean_block_nrg = 0; move32(); + FOR (i = 0; i < yLen; i++) + { + tmp16 = shl_sat(in_sig[i], sub(s, 4)); + mean_block_nrg = L_mac0(mean_block_nrg, tmp16, tmp16); /* exp = 2s - 8 */ + } + + s2 = getScaleFactor16(&yLen, 1); + c = shl(yLen, s2); + mean_block_nrg16 = div_l(mean_block_nrg, c); /* exp = 2s - 8 - s2 - 1 */ + mean_block_nrg = L_shl(L_mult0(mean_block_nrg16, BLOCK_SIZE * THR1), add(4, s2)); /* exp = 2s - 5 */ + + maxPeak = 0; move32(); + c = sub(yLen, 2 * BLOCK_SIZE); + + test(); + IF (abs_s(in_sig[0]) >= abs_s(in_sig[1])) + { + block_cent = 0; move32(); + FOR (j = 0; j <= 1; j++) + { + tmp16 = shl_sat(in_sig[j], sub(s, 2)); + block_cent = L_mac0(block_cent, tmp16, tmp16); /* -> exp = 2s - 4 */ + } + block_cent = L_shr(block_cent, 1); /* exp = 2s - 5 */ + + IF (L_sub(block_cent, mean_block_nrg) > 0) + { + cur_max = abs_s(in_sig[0]); + cur_max = MAX(abs_s(in_sig[1]), cur_max); + + next_max = abs_s(in_sig[-1 + BLOCK_SIZE]); + next_max = MAX(abs_s(in_sig[-1 + BLOCK_SIZE + 1]), next_max); + next_max = MAX(abs_s(in_sig[-1 + BLOCK_SIZE + 2]), next_max); + + IF (sub(cur_max, next_max) > 0) + { + maxPeak = block_cent; move32(); + *xover = 1; + } + } + } + + FOR (i = 0; i < BLOCK_SIZE; i++) + { + test(); + IF (abs_s(in_sig[i + 1]) >= abs_s(in_sig[i]) && abs_s(in_sig[i + 1]) >= abs_s(in_sig[i + 2])) + { + block_cent = 0; move32(); + FOR (j = 0; j < BLOCK_SIZE; j++) + { + tmp16 = shl_sat(in_sig[i + j], sub(s, 2)); + block_cent = L_mac0(block_cent, tmp16, tmp16); /* -> exp = 2s - 4 */ + } + block_cent = L_shr(block_cent, 1); /* exp = 2s - 5 */ + + IF (L_sub(block_cent, mean_block_nrg) > 0) + { + cur_max = abs_s(in_sig[i]); + cur_max = MAX(abs_s(in_sig[i + 1]), cur_max); + cur_max = MAX(abs_s(in_sig[i + 2]), cur_max); + + prev_max = 0; move16(); + FOR (j = i - BLOCK_SIZE; j <= i - 1; j++) + { + IF (j > 0) + { + prev_max = MAX(abs_s(in_sig[j]), prev_max); + } + } + + next_max = abs_s(in_sig[i + BLOCK_SIZE]); + next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 1]), next_max); + next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 2]), next_max); + + test(); + IF (sub(cur_max, prev_max) >= 0 && sub(cur_max, next_max) > 0) + { + IF (L_sub(block_cent, maxPeak) >= 0) + { + maxPeak = block_cent; move32(); + *xover = sub(add(i, BLOCK_SIZE), 1); + } + ELSE + { + tmp32 = L_mult(FAC, extract_h(maxPeak)); + + tmp16 = extract_l(L_shr(maxPeak, 1)); + tmp16 = s_and(tmp16, 0x7fff); + tmp16 = mult(FAC, tmp16); + tmp32 = L_add_sat(tmp32, tmp16); + + IF (L_sub(block_cent, tmp32) > 0) + { + *xover = sub(add(i, BLOCK_SIZE), 1); + } + } + } + } + } + } + + FOR (i = BLOCK_SIZE; i <= c; i++) + { + test(); + IF (abs_s(in_sig[i + 1]) >= abs_s(in_sig[i]) && abs_s(in_sig[i + 1]) >= abs_s(in_sig[i + 2])) + { + block_cent = 0; move32(); + FOR (j = 0; j < BLOCK_SIZE; j++) + { + tmp16 = shl_sat(in_sig[i + j], sub(s, 2)); + block_cent = L_mac0(block_cent, tmp16, tmp16); /* -> exp = 2s - 4 */ + } + block_cent = L_shr(block_cent, 1); /* exp = 2s - 5 */ + + IF (L_sub(block_cent, mean_block_nrg) > 0) + { + cur_max = abs_s(in_sig[i]); + cur_max = MAX(abs_s(in_sig[i + 1]), cur_max); + cur_max = MAX(abs_s(in_sig[i + 2]), cur_max); + + prev_max = abs_s(in_sig[i - BLOCK_SIZE]); + prev_max = MAX(abs_s(in_sig[i - BLOCK_SIZE + 1]), prev_max); + prev_max = MAX(abs_s(in_sig[i - BLOCK_SIZE + 2]), prev_max); + + next_max = abs_s(in_sig[i + BLOCK_SIZE]); + next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 1]), next_max); + next_max = MAX(abs_s(in_sig[i + BLOCK_SIZE + 2]), next_max); + + test(); + IF (sub(cur_max, prev_max) >= 0 && sub(cur_max, next_max) > 0) + { + IF (L_sub(block_cent, maxPeak) >= 0) + { + maxPeak = block_cent; move32(); + *xover = sub(add(i, BLOCK_SIZE), 1); + } + ELSE + { + tmp32 = L_mult(FAC, extract_h(maxPeak)); + + tmp16 = extract_l(L_shr(maxPeak, 1)); + tmp16 = s_and(tmp16, 0x7fff); + tmp16 = mult(FAC, tmp16); + tmp32 = L_add_sat(tmp32, tmp16); + + IF (L_sub(block_cent, tmp32) > 0) + { + *xover = sub(add(i, BLOCK_SIZE), 1); + } + } + } + } + } + } + + Dyn_Mem_Deluxe_Out(); +} + + diff --git a/lib_lc3plus/pc_main_fx.c b/lib_lc3plus/pc_main_fx.c new file mode 100644 index 000000000..708f79d74 --- /dev/null +++ b/lib_lc3plus/pc_main_fx.c @@ -0,0 +1,57 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "constants.h" +#include "functions.h" + +void processPCmain_fx(Word16 rframe, Word16 *bfi, Word16 yLen, Word16 frame_dms, Word16 q_old_res_fx[], + Word16 *q_old_res_fx_exp, +#ifdef ENABLE_HR_MODE + Word32 q_res_fx[], +#else + Word16 q_res_fx[], +#endif + Word16 q_old_d_fx[], Word16 spec_inv_idx, + Word16 pitch_present, Word16 stab_fac, Word32 q_d_fx[], Word16 *q_fx_exp, + Word16 gg_idx, Word16 gg_idx_off, Word16 *prev_gg, Word16 *prev_gg_e, Word16 *BW_cutoff_idx_nf, + Word16 *prev_BW_cutoff_idx_nf, Word16 fac_ns_idx, Word16 *prev_fac_ns_fx, Word16 *pc_nbLostFramesInRow) +{ + Dyn_Mem_Deluxe_In( + Word16 fac, fac_e; + ); + + fac = 32767; fac_e = 0; + + IF (sub(*bfi, 2) == 0) + { + processPCclassify_fx(pitch_present, frame_dms, q_old_d_fx, q_old_res_fx, yLen, spec_inv_idx, stab_fac, bfi); + } + + IF (sub(*bfi, 2) == 0) + { + processPCapply_fx(yLen, q_old_res_fx, q_old_res_fx_exp, q_res_fx, q_old_d_fx, spec_inv_idx, + &fac, &fac_e, q_d_fx, q_fx_exp, gg_idx, gg_idx_off, *prev_gg, *prev_gg_e, pc_nbLostFramesInRow); + } + + IF (sub(*bfi, 1) != 0) + { + processPCupdate_fx(*bfi, yLen, q_old_res_fx, q_old_res_fx_exp, q_res_fx, spec_inv_idx, gg_idx, gg_idx_off, prev_gg, + prev_gg_e, rframe, BW_cutoff_idx_nf, prev_BW_cutoff_idx_nf, fac_ns_idx, prev_fac_ns_fx, fac, fac_e); + } + + if (*bfi == 0) + { + *pc_nbLostFramesInRow = 0; move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + + diff --git a/lib_lc3plus/pc_update_fx.c b/lib_lc3plus/pc_update_fx.c new file mode 100644 index 000000000..17b719bcd --- /dev/null +++ b/lib_lc3plus/pc_update_fx.c @@ -0,0 +1,148 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "constants.h" +#include "functions.h" + +#ifdef ENABLE_HR_MODE + +void Copy_Scale_sig_32(const Word32 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Counter i; + Word16 tmp; + + if (exp0 == 0) + { + for (i = 0; i < lg; i++) + { + y[i] = extract_h(x[i]); + } + + return; + } + + tmp = s_max(exp0, -31); + tmp = s_min(tmp, 31); + + for (i = 0; i < lg; i++) + { + y[i] = extract_h(L_shr_r(x[i], -tmp)); + } +} +#endif + +void processPCupdate_fx(Word16 bfi, Word16 yLen, Word16 q_old_res_fx[], Word16 *q_old_res_fx_exp, +#ifdef ENABLE_HR_MODE + Word32 q_res_fx[], +#else + Word16 q_res_fx[], +#endif + Word16 spec_inv_idx, Word16 gg_idx, Word16 gg_idx_off, + Word16 *prev_gg, Word16 *prev_gg_e, Word16 rframe, Word16 *BW_cutoff_idx_nf, + Word16 *prev_BW_cutoff_idx_nf, Word16 fac_ns_idx, Word16 *prev_fac_ns_fx, Word16 fac, + Word16 fac_e) +{ + Word16 global_gain, global_gain_e, s, s2, s3, tmp16; + Word32 tmp32; + +#ifdef DYNMEM_COUNT + struct _dynmem + { + Word16 global_gain, global_gain_e, s, s2, s3, tmp16; + Word32 tmp32; + }; + Dyn_Mem_In("processPCupdate_fx", sizeof(struct _dynmem)); +#endif + + tmp32 = L_shl_pos(L_mult0(add(gg_idx, gg_idx_off), 0x797D), 7); + global_gain_e = add(extract_l(L_shr_pos(tmp32, 25)), 1); + global_gain = round_fx(BASOP_Util_InvLog2_lc3plus(L_or(tmp32, 0xFE000000))); + + *prev_gg = global_gain; move16(); + *prev_gg_e = global_gain_e; move16(); + +#ifdef ENABLE_HR_MODE + s = getScaleFactor32_lc3plus(q_res_fx, spec_inv_idx); /* exp = 0 */ +#else + s = getScaleFactor16(q_res_fx, spec_inv_idx); /* exp = 0 */ +#endif + + IF (bfi == 0) + { + *q_old_res_fx_exp = negate(s); +#ifdef ENABLE_HR_MODE + Copy_Scale_sig_32(q_res_fx, q_old_res_fx, yLen, s); + *q_old_res_fx_exp = *q_old_res_fx_exp + 16; +#else + Copy_Scale_sig(q_res_fx, q_old_res_fx, yLen, s); +#endif + } + ELSE + { +#ifdef ENABLE_HR_MODE + s2 = getScaleFactor32_lc3plus(&q_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */ + IF (s2 == 0) + s2 = 16; + s3 = add(s, *q_old_res_fx_exp); + IF (sub(s3, s2) > 0) + { + tmp16 = sub(s3, s2); + s = sub(s, tmp16); + } + s2 = add(s, *q_old_res_fx_exp); + *q_old_res_fx_exp = negate(s) + 16; + + + if (s2 > -32) + { + Copy_Scale_sig_32(&q_res_fx[spec_inv_idx], &q_old_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx), s2); + } +#else + s2 = getScaleFactor16(&q_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx)); /* exp = q_old_res_fx_exp */ + s3 = add(s, *q_old_res_fx_exp); + IF (sub(s3, s2) > 0) + { + tmp16 = sub(s3, s2); + s = sub(s, tmp16); + } + s2 = add(s, *q_old_res_fx_exp); + *q_old_res_fx_exp = negate(s); + + s = s_max(s_min(s, 15), -15); + s2 = s_max(s_min(s2, 15), -15); + Copy_Scale_sig(q_res_fx, q_old_res_fx, spec_inv_idx, s); + Copy_Scale_sig(&q_res_fx[spec_inv_idx], &q_old_res_fx[spec_inv_idx], sub(yLen, spec_inv_idx), s2); +#endif + } + + IF (rframe == 0) + { + *prev_BW_cutoff_idx_nf = *BW_cutoff_idx_nf; + *prev_fac_ns_fx = shl_pos(sub(8, fac_ns_idx), 11); + } + ELSE IF(sub(bfi, 2) == 0 && sub(*BW_cutoff_idx_nf, *prev_BW_cutoff_idx_nf) != 0 + && sub(spec_inv_idx, yLen) < 0) + { + *BW_cutoff_idx_nf = *prev_BW_cutoff_idx_nf; + *prev_fac_ns_fx = shl_sat(mult(*prev_fac_ns_fx, fac), fac_e); + *prev_fac_ns_fx = s_max(*prev_fac_ns_fx, 2048); + *prev_fac_ns_fx = s_min(*prev_fac_ns_fx, 16384); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/per_band_energy_fx.c b/lib_lc3plus/per_band_energy_fx.c new file mode 100644 index 000000000..14e853212 --- /dev/null +++ b/lib_lc3plus/per_band_energy_fx.c @@ -0,0 +1,275 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include "rom_basop_util.h" + +void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Word16 d_fx_exp, + const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, Word16 frame_dms, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +) +{ + Dyn_Mem_Deluxe_In(Counter i, k, band; Word16 s; Word16 s1; Word16 s2; Word32 nrg; Word16 smax; Word16 tmp16; + Word16 nbands; Word16 maxBwBin; Word16 stopBand; Word16 bandsOffsetOne; Word16 bandsOffsetTwo; + Word16 * d2_band_fx_exp;); + + + d2_band_fx_exp = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_BANDS_NUMBER_PLC bytes */ + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + maxBwBin = MAX_BW_HR; + fs_idx = fs_idx + 1; + move16(); + } + else +#endif + { + maxBwBin = MAX_BW; + move16(); + } + + SWITCH (frame_dms) + { + case 25: maxBwBin = maxBwBin >> 2; move16(); + { + bandsOffsetOne = bands_offset_with_one_max_2_5ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_2_5ms[fs_idx]; + move16(); + } + BREAK; + case 50: maxBwBin = maxBwBin >> 1; move16(); + { + bandsOffsetOne = bands_offset_with_one_max_5ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_5ms[fs_idx]; + move16(); + } + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + maxBwBin = (maxBwBin >> 2) * 3; move16(); + bandsOffsetOne = bands_offset_with_one_max_7_5ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_7_5ms[fs_idx]; + move16(); + BREAK; +#endif + default: /* 100 */ + { + bandsOffsetOne = bands_offset_with_one_max[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max[fs_idx]; + move16(); + } + BREAK; + } + + IF (sub(linear, 1) == 0) + { + + #ifdef ENABLE_HR_MODE + if (hrmode) + { + fs_idx = fs_idx - 1; + } + #endif + + SWITCH (frame_dms) + { + case 25: + bandsOffsetOne = bands_offset_with_one_max_lin_2_5ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_lin_2_5ms[fs_idx]; + move16(); + BREAK; + case 50: + bandsOffsetOne = bands_offset_with_one_max_lin_5ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_lin_5ms[fs_idx]; + move16(); + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + bandsOffsetOne = bands_offset_with_one_max_lin_7_5ms[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_lin_7_5ms[fs_idx]; + move16(); + BREAK; +#endif + case 100: + bandsOffsetOne = bands_offset_with_one_max_lin[fs_idx]; + move16(); + bandsOffsetTwo = bands_offset_with_two_max_lin[fs_idx]; + move16(); + BREAK; + } + } + + /* start processing with band offsets == 1 */ + FOR (band = 0; band < bandsOffsetOne; band++) + { + ASSERT((band_offsets[band + 1] - band_offsets[band]) == 1); + ASSERT(band < maxBwBin); + + s2 = 15; + move16(); + s = norm_l(d_fx[band]); + if (d_fx[band] != 0) + s2 = s_min(s2, s); + + tmp16 = extract_h(L_shl_pos(d_fx[band], s2)); + + d2_fx[band] = L_mult0(tmp16, tmp16); + move32(); + d2_band_fx_exp[band] = sub(1, shl_pos(s2, 1)); + move16(); + } + + /* start processing with band offsets == 2 */ + i = bandsOffsetOne; + move16(); + FOR (; band < bandsOffsetTwo; band++) + { + ASSERT((band_offsets[band + 1] - band_offsets[band]) == 2); + IF (sub(add(i, 1), maxBwBin) >= 0) + { + IF (sub(i, maxBwBin) >= 0) + { + d2_fx[band] = 0; + move32(); + d2_band_fx_exp[band] = sub(1, shl_pos(15, 1)); + move16(); + } + ELSE + { + s2 = 15; + move16(); + s = norm_l(d_fx[band]); + if (d_fx[band] != 0) + s2 = s_min(s2, s); + + tmp16 = extract_h(L_shl_pos(d_fx[band], s2)); + + d2_fx[band] = L_mult0(tmp16, tmp16); + move32(); + d2_band_fx_exp[band] = sub(1, shl_pos(s2, 1)); + move16(); + } + } + ELSE + { + ASSERT(i + 1 < maxBwBin); + + s2 = 15; + move16(); + s = norm_l(d_fx[i]); + if (d_fx[i] != 0) + s2 = s_min(s2, s); + s = norm_l(d_fx[i + 1]); + if (d_fx[i + 1] != 0) + s2 = s_min(s2, s); + + tmp16 = extract_h(L_shl_pos(d_fx[i], s2)); + nrg = L_mult0(tmp16, tmp16); + nrg = L_min(nrg, 0x3FFFFFFF); + tmp16 = extract_h(L_shl_pos(d_fx[i + 1], s2)); + + d2_fx[band] = L_shr_pos(L_mac0(nrg, tmp16, tmp16), 1); + move32(); + d2_band_fx_exp[band] = sub(1, shl_pos(s2, 1)); + move16(); + } + i = add(i, 2); + } + + /* proceed with band offsets > 2 */ + FOR (; band < n_bands; band++) + { + /* normalization */ + k = i; + move16(); + s1 = 15; + move16(); + + stopBand = s_min(band_offsets[band + 1], maxBwBin); + FOR (; k < stopBand; k++) + { + s = norm_l(d_fx[k]); + if (d_fx[k] != 0) + s1 = s_min(s1, s); + } + + nbands = sub(band_offsets[band + 1], band_offsets[band]); +#ifdef ENABLE_HR_MODE + if (nbands < 32) + { + nbands = s_min(s_max(0, nbands), 31); + /* specify headroom, it can be reduced by one due to use of L_mac0 */ + s2 = sub(s1, bands_nrg_scale[nbands]); + } + else + { + /* Active only in the 96 kHz case */ + s2 = sub(s1, 5); + } +#else + ASSERT(nbands < 32); + nbands = s_min(s_max(0, nbands), 31); + /* specify headroom, it can be reduced by one due to use of L_mac0 */ + s2 = sub(s1, bands_nrg_scale[nbands]); +#endif + + /* calculate energy per band */ + nrg = 0; + move32(); + + FOR (; i < stopBand; i++) + { + tmp16 = extract_h(L_shl(d_fx[i], s2)); + nrg = L_mac0(nrg, tmp16, tmp16); + } + i = band_offsets[band + 1]; + + /* calculate mean value of energy */ + nrg = Mpy_32_16_lc3plus(nrg, InvIntTable[nbands]); + + /* store normalized energy */ + s = norm_l(nrg); + d2_fx[band] = L_shl_pos(nrg, s); + move32(); + d2_band_fx_exp[band] = sub(1, add(shl_pos(s2, 1), s)); + move16(); + } + + /* Determine maximum exponent and rescale band energies */ + smax = -31; + move16(); + FOR (band = 0; band < n_bands; band++) + { + smax = s_max(smax, d2_band_fx_exp[band]); + } + FOR (band = 0; band < n_bands; band++) + { + d2_fx[band] = L_shr_pos(d2_fx[band], s_min(sub(smax, d2_band_fx_exp[band]), 31)); + move32(); + } + + /* Save exponent for all bands */ + *d2_fx_exp = s_max(add(shl_pos(d_fx_exp, 1), smax), -32); + move16(); + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/plc_apply_fx.c b/lib_lc3plus/plc_apply_fx.c new file mode 100644 index 000000000..9430d155e --- /dev/null +++ b/lib_lc3plus/plc_apply_fx.c @@ -0,0 +1,419 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "constants.h" +#include "functions.h" + +void processPLCapply_fx( +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 *concealMethod, +#else + Word16 concealMethod, +#endif + Word16 nbLostFramesInRow, Word16 bfi, Word16 prev_bfi, + Word16 frame_length, Word16 la_zeroes, +#ifdef ENABLE_HR_MODE + const Word32 w[], +#else + const Word16 w[], +#endif + Word16 x_fx[], Word16 ola_mem[], + Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], + Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, Word16 *damping, Word16 old_pitch_int, + Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, Word16 frame_dms, AplcSetup *plcAd, + Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + , Word32 rel_pitch_change +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + , Word16 *alpha_type_2_table +#endif + ) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word32 *d2_fx; + Word32 *q_old_d_fx32; + Word32 *r_fx; + Word32 *tdc_A_32; + Word16 d2_fx_exp; + Word16 r_fx_exp; + Word16 Q_syn; + Word8 * buffer_perBandEnergy, *buffer_preEmphasis, *buffer_InverseODFT, *buffer_Levinson, + *buffer_tdac, *buffer_phecu; + Word16 y_e; /*exponent of L_ecu_rec */ + Word16 tmp_is_trans[2]; /* may be changed to a single variable */ + Word16 env_stab; + + Word16 n_bands, prev_bfi_plc2; + const Word16 *band_offsets; + Word32 * L_ecu_rec; /* local xtda output is MAX_LEN -> input buffer, + as tmp buffer for w32 fft MAX_LPROT */ + ); +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 consecutiveLostThreshold = 0; +#endif + +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + Word16 thresh_tdc_cnt; + Word16 thresh_ns_cnt; + Word16 thresh_tdc_ns_cnt; +#endif + + band_offsets = NULL; + + d2_fx = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_BANDS_NUMBER_PLC */ + q_old_d_fx32 = (Word32 *)scratchAlign(d2_fx, sizeof(*d2_fx) * MAX_BANDS_NUMBER_PLC); /* Size = 4 * MAX_BW */ + r_fx = (Word32 *)scratchAlign(d2_fx, sizeof(*d2_fx) * MAX_BANDS_NUMBER_PLC); /* Size = 4 * (M + 1) */ + tdc_A_32 = (Word32 *)scratchAlign(r_fx, sizeof(*r_fx) * (M + 1)); /* Size = 4 * (M + 1) */ + + L_ecu_rec = (Word32 *)scratchAlign(tdc_A_32, sizeof(*tdc_A_32) * (M + 1)); /* Size = 4 * MAX_LPROT bytes */ + + buffer_perBandEnergy = + (Word8 *)scratchAlign(q_old_d_fx32, sizeof(*q_old_d_fx32) * (MAX_LEN)); /* Size = 2 * MAX_BANDS_NUMBER_PLC */ + buffer_preEmphasis = + (Word8 *)scratchAlign(tdc_A_32, sizeof(*tdc_A_32) * (M + 1)); /* Size = 2 * MAX_BANDS_NUMBER_PLC */ + buffer_InverseODFT = buffer_preEmphasis; /* Size = 640 bytes */ + buffer_Levinson = buffer_preEmphasis; /* Size = 4 * (M + 1) */ + + buffer_tdac = scratchBuffer; /* Size = 2 * MAX_LEN bytes */ + buffer_phecu = scratchBuffer; /* Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */ + /* Buffers overlap since they are not used at once */ + + + UNUSED(ns_cum_alpha); + UNUSED(ns_seed); + + /* Apply/Prepare PLC in bfi-case */ + IF (sub(bfi, 1) == 0) + { + +#ifdef CR8_A_PLC_FADEOUT_TUNING + SWITCH(frame_dms) + { + case 25: + consecutiveLostThreshold = 16; +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + thresh_tdc_cnt = THRESH_025_DMS_TDC_CNT; + thresh_ns_cnt = THRESH_025_DMS_NS_CNT; + thresh_tdc_ns_cnt = THRESH_025_DMS_TDC_NS_CNT; +#endif + break; + case 50: consecutiveLostThreshold = 8; +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + thresh_tdc_cnt = THRESH_050_DMS_TDC_CNT; + thresh_ns_cnt = THRESH_050_DMS_NS_CNT; + thresh_tdc_ns_cnt = THRESH_050_DMS_TDC_NS_CNT; +#endif + break; + case 75: consecutiveLostThreshold = 6; +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + thresh_tdc_cnt = THRESH_075_DMS_TDC_CNT; + thresh_ns_cnt = THRESH_075_DMS_NS_CNT; + thresh_tdc_ns_cnt = THRESH_075_DMS_TDC_NS_CNT; +#endif + break; + case 100: consecutiveLostThreshold = 4; +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + thresh_tdc_cnt = THRESH_100_DMS_TDC_CNT; + thresh_ns_cnt = THRESH_100_DMS_NS_CNT; + thresh_tdc_ns_cnt = THRESH_100_DMS_TDC_NS_CNT; +#endif + break; + default: assert(0); + } + + IF (sub(fs_idx, 2) == 0 || sub(fs_idx, 4) >= 0) + { +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + if (sub(plcAd->longterm_counter_plcTdc, thresh_tdc_cnt) < 0){ + plcAd->plc_fadeout_type = 1; + } + else if (sub(plcAd->longterm_counter_plcNsAdv, thresh_ns_cnt) < 0){ + plcAd->plc_fadeout_type = 1; + } + else if (sub(plcAd->longterm_counter_plcTdc + plcAd->longterm_counter_plcNsAdv, thresh_tdc_ns_cnt) < 0){ + plcAd->plc_fadeout_type = 1; + } + else { + plcAd->plc_fadeout_type = 0; + } + +#else + IF (((sub(plcAd->longterm_counter_plcPhaseEcu, L_shr_pos(Mpy_32_16_lc3plus(FAC1_FADEOUT, plcAd->longterm_counter_plcTdc), SHIFT1_FADEOUT)) < 0) || + (sub(plcAd->longterm_counter_plcPhaseEcu, L_shr_pos(Mpy_32_16_lc3plus(FAC1_FADEOUT, plcAd->longterm_counter_plcNsAdv), SHIFT1_FADEOUT)) < 0)) && + (sub(plcAd->longterm_counter_plcTdc, L_shr_pos(Mpy_32_16_lc3plus(FAC2_FADEOUT, plcAd->longterm_counter_plcNsAdv), SHIFT2_FADEOUT)) < 0)) + { + plcAd->plc_fadeout_type = 0; + } + ELSE + { + IF ((sub(plcAd->longterm_counter_plcPhaseEcu, L_shr_pos(Mpy_32_16_lc3plus(FAC3_FADEOUT, plcAd->longterm_counter_plcTdc), SHIFT3_FADEOUT)) > 0) || + (sub(plcAd->longterm_counter_plcPhaseEcu, L_shr_pos(Mpy_32_16_lc3plus(FAC3_FADEOUT, plcAd->longterm_counter_plcNsAdv), SHIFT3_FADEOUT)) > 0)) + { + plcAd->plc_fadeout_type = 1; + } ELSE { + plcAd->plc_fadeout_type = 0; + } + } +#endif + + + env_stab = norm_s(plcAd->longterm_analysis_counter_max); + IF(sub(shl_pos(plcAd->overall_counter, env_stab), mult(shl_pos(plcAd->longterm_analysis_counter_max, env_stab), PLC_LONGTERM_ANALYSIS_STARTUP_FILL)) < 0) + { + plcAd->plc_fadeout_type = 0; + } + +#ifndef CR9_H_REMOVE_SWITCH_TO_PLC_NS + IF (sub(nbLostFramesInRow, consecutiveLostThreshold) >= 0 && sub(plcAd->plc_fadeout_type, 1) == 0) + { + IF (sub(*concealMethod, LC3_CON_TEC_TDPLC) == 0) + { + *concealMethod = LC3_CON_TEC_NS_ADV; + } + } +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + IF (L_sub(rel_pitch_change,REL_PITCH_THRESH) > 0 && sub(hrmode,1) == 0 && (sub(frame_dms,50) == 0 || sub(frame_dms,25) == 0)){ + plcAd->plc_fadeout_type = 2;move16(); + } ELSE +#endif + IF((sub(nbLostFramesInRow, consecutiveLostThreshold) < 0) && (*concealMethod != LC3_CON_TEC_PHASE_ECU)) + { + plcAd->plc_fadeout_type = 0; + } + } ELSE { + plcAd->plc_fadeout_type = 0; /*fs_idx == 0,1,3 */ + } +#endif /* CR8_A_PLC_FADEOUT_TUNING */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING + SWITCH (*concealMethod) +#else + SWITCH (concealMethod) +#endif + { + case LC3_CON_TEC_PHASE_ECU: + ASSERT(frame_dms == 100); + /* call phaseEcu */ + env_stab = 32767; move16(); /* 1.0=stable , 0.0=dynamic Q15*/ + tmp_is_trans[0] = plcAd->PhECU_short_flag_prev; move16(); + tmp_is_trans[1] = plcAd->PhECU_short_flag_prev; move16(); + + ASSERT(prev_bfi == 0 || prev_bfi == 1|| prev_bfi == 2); /*PC prev_bfi has three states */ + prev_bfi_plc2 = prev_bfi; move16(); + if (sub(prev_bfi_plc2, 2) == 0) + { + prev_bfi_plc2 = 0; move16(); + } + + ASSERT(prev_bfi_plc2 == 0 || prev_bfi_plc2 == 1); /*PhEcu does not accept prev_bfi == 2 */ + IF(prev_bfi_plc2 == 0) + { /* convert pitch lag info at current fs to a normalized fractional bin-frequency */ + plcAd->PhECU_f0hzLtpBinQ7 = plc_phEcuSetF0Hz_fx(fs_idx, old_pitch_int, old_pitch_fr); move16(); + + + + /* first bfi frame calc decoded pcm energy 16,16 ms, in 26 ms buffer separated by 10 ms*/ + + { /* compute energy normalization needed for concealment method 2 Xavg and transient analysis */ + + /* left */ + processPLCUpdateXFP_w_E_hist_fx(0, 0, + &(plcAd->x_old_tot_fx[ sub(plcAd->max_len_pcm_plc , add(num_FsByResQ0[fs_idx],rectLengthTab[fs_idx] )) ]), plcAd->q_fx_old_exp,0, + + fs_idx, + &plcAd->PhECU_L_oold_xfp_w_E_fx, &plcAd->PhECU_oold_xfp_w_E_exp_fx, + &plcAd->PhECU_L_old_xfp_w_E_fx, &plcAd->PhECU_old_xfp_w_E_exp_fx, + &plcAd->PhECU_oold_Ltot_exp_fx, &plcAd->PhECU_old_Ltot_exp_fx); + + /* right */ + processPLCUpdateXFP_w_E_hist_fx(0, 0, plcAd->PhECU_xfp_fx, plcAd->PhECU_xfp_exp_fx, + plcAd->PhECU_margin_xfp, fs_idx, + &plcAd->PhECU_L_oold_xfp_w_E_fx, &plcAd->PhECU_oold_xfp_w_E_exp_fx, + &plcAd->PhECU_L_old_xfp_w_E_fx, &plcAd->PhECU_old_xfp_w_E_exp_fx, + &plcAd->PhECU_oold_Ltot_exp_fx, &plcAd->PhECU_old_Ltot_exp_fx); + } + } + + hq_phase_ecu_fx( + plcAd->PhECU_xfp_fx, /* i : only valid first Bfi frame , buffer of previous synt signal length */ + L_ecu_rec, /* o : reconstructed frame in folded tda domain xtda Word32 Q x */ + &plcAd->PhECU_time_offs, /* i/o: Sample offset for consecutive frame losses*/ + plcAd->PhECU_X_sav_fx, /* i(prev_bfi==1)/o(prev_bfi==0): Stored Complex spectrum of prototype frame */ + &plcAd->PhECU_X_savQ_fx, /* i/o: Q value of stored spectrum */ + &plcAd->PhECU_num_plocs, /* i/o: Number of identified peaks */ + plcAd->PhECU_plocs, /* i/o: Peak locations Q0 */ + plcAd->PhECU_f0est, /* i/o: Interpolated peak locations Q16 */ + env_stab, /* i : Envelope stability parameter */ + plcAd->PhECU_f0hzLtpBinQ7, /* i: LTP bin frequency in normalized Hz Q7 */ + plcAd->norm_corrQ15_fx, /* i : correlation for lag at f0hzLtpBinQ7 */ + prev_bfi_plc2, /* i : indicating burst frame error */ + tmp_is_trans, /* i : flags indicating previous transient frames */ + plcAd->PhECU_mag_chg_1st, /* i/o: per band magnitude modifier for transients*/ + NULL, /* o: dbg per band magnitude modifier, incl. burst attenuation */ + plcAd->PhECU_Xavg, /* i/o: Frequency group average gain to fade to */ + &plcAd->PhECU_beta_mute, /* o : Factor for long-term mute */ + fs_idx, /* i : Encoded bandwidth "nb(0),WB,sWB,WB,FB" */ + frame_length, /* i : frame length */ + NULL , /* o : seed synch dbg */ + NULL , /* o : evolved Spectrum dbg */ + plcAd->PhECU_t_adv, /* i : time adjustment excluding time_offs */ + PhECU_wins[fs_idx][2], /* i: 2 ms initial part pre_tda = mdct-ana */ + PhECU_wins[fs_idx][1], /* i: 16 ms pretda combined part IWHR+MDCT-ana */ + PhECU_wins[fs_idx][0], + plcAd->PhECU_xfp_exp_fx, + plcAd->max_lprot, + plcAd->max_plocs, + plcAd->PhECU_L_oold_xfp_w_E_fx,plcAd->PhECU_oold_xfp_w_E_exp_fx, plcAd->PhECU_oold_Ltot_exp_fx, + plcAd->PhECU_oold_grp_shape_fx, + plcAd->PhECU_L_old_xfp_w_E_fx,plcAd->PhECU_old_xfp_w_E_exp_fx, plcAd->PhECU_old_Ltot_exp_fx, + plcAd->PhECU_old_grp_shape_fx, + plcAd->PhECU_margin_xfp, +#ifdef CR8_A_PLC_FADEOUT_TUNING + plcAd->plc_fadeout_type , /* i : fadeout scheme */ + &(plcAd->PhECU_nonpure_tone_flag), /* i/o : non-pure single tone indicator state */ +#endif + buffer_phecu); + + y_e = 18; move16(); /* the fixed exponent (exp) from Lecu_rec from PhaseECU is 18 */ + + Processing_ITDA_WIN_OLA( + L_ecu_rec, /* i: X_TDA buffer data = "y" DCT-IV output */ + &y_e, /* i/o: x_tda exponent "y_e" */ + w, /* i: window coefficients including normalization of sqrt(2/N) and scaled by 2^4 */ + ola_mem, /* i/o: overlap add memory */ + ola_mem_exp, /* i/o: overlap add exponent */ + x_fx, /* o: time signal out */ + LowDelayShapes_n960_len[fs_idx], /* i: window length */ + frame_length, /* i: block size */ + sub(frame_length, LowDelayShapes_n960_la_zeroes[fs_idx]) /* i: overlap add buffer size */ + ); + *q_fx_exp = y_e; move16(); /* assign updated Q */ + BREAK; + + case LC3_CON_TEC_TDPLC: + IF (sub(nbLostFramesInRow, 1) == 0) + { + plcAd->tdc_fract = old_pitch_fr; move16(); + n_bands = s_min(frame_length, MAX_BANDS_NUMBER_PLC); + SWITCH (frame_dms) + { + case 25: + band_offsets = bands_offset_lin_2_5ms[fs_idx]; move16(); + IF (sub(fs_idx, 4) == 0) + { + n_bands = 60; move16(); + } + BREAK; + case 50: + band_offsets = bands_offset_lin_5ms[fs_idx]; move16(); + IF (sub(fs_idx, 2) == 0) + { + n_bands = 40; move16(); + } + BREAK; +# ifdef CR8_G_ADD_75MS + case 75: + band_offsets = bands_offset_lin_7_5ms[fs_idx]; move16(); +# ifdef ENABLE_HR_MODE + IF (sub(fs_idx, 5) != 0) + { +# endif + IF (sub(fs_idx, 3) != 0) + { + n_bands = 60; move16(); + } +# ifdef ENABLE_HR_MODE + } +# endif + BREAK; +# endif + case 100: + band_offsets = bands_offset_lin[fs_idx]; move16(); + BREAK; + } + + FOR (i = 0; i < yLen; i++) + { + q_old_d_fx32[i] = L_deposit_h(q_old_d_fx[i]); + } + + /* LPC Analysis */ + /* calculate per band energy*/ + processPerBandEnergy_fx(d2_fx, &d2_fx_exp, q_old_d_fx32, *q_old_fx_exp, band_offsets, fs_idx, n_bands, + 1, frame_dms, buffer_perBandEnergy +#ifdef ENABLE_HR_MODE + , hrmode +#endif + ); + + /* calculate pre-emphasis */ + processPreEmphasis_fx(d2_fx, &d2_fx_exp, fs_idx, n_bands, frame_dms, buffer_preEmphasis); + + /* inverse ODFT */ + processInverseODFT_fx(r_fx, &r_fx_exp, d2_fx, d2_fx_exp, n_bands, plcAd->tdc_lpc_order, buffer_InverseODFT); + + /* lag windowing */ + processLagwin_fx(r_fx, lag_win[fs_idx], plcAd->tdc_lpc_order); + + /* Levinson Durbin */ + processLevinson_fx(tdc_A_32, r_fx, plcAd->tdc_lpc_order, NULL, NULL, buffer_Levinson); + + /* 32Q27 -> 16Qx */ + processPLCLpcScaling_fx(tdc_A_32, plcAd->tdc_A, add(plcAd->tdc_lpc_order, 1)); + } + + /* call TD-PLC */ + /* Q_syn = plcAd->q_fx_old_exp; */ /* makes q_fx_old_exp + available in processTimeDomainConcealment_Apply_fx() for + debugging */ + processTimeDomainConcealment_Apply_fx( + old_pitch_int, plcAd->tdc_preemph_fac, plcAd->tdc_A, plcAd->tdc_lpc_order, plcAd->x_old_tot_fx, frame_length, frame_dms, + fs_idx, nbLostFramesInRow, sub(frame_length, la_zeroes), plcAd->stab_fac, &plcAd->tdc_fract, + &plcAd->tdc_seed, + &plcAd->tdc_gain_c, x_fx, &Q_syn, damping, + plcAd->max_len_pcm_plc, + plcAd->harmonicBuf_fx, plcAd->synthHist_fx, &plcAd->harmonicBuf_Q, scratchBuffer +#ifdef CR9_I_INC_TDC_FADEOUT_LEN + , plcAd->plc_fadeout_type +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + , alpha_type_2_table +#endif +); + + /* exponent of TD-PLC output */ + Q_syn = add(Q_syn, sub(15, plcAd->q_fx_old_exp)); + *q_fx_exp = sub(15, Q_syn); move16(); + + /* TDAC */ + processTdac_fx(ola_mem, ola_mem_exp, x_fx, *q_fx_exp, w, la_zeroes, frame_length, buffer_tdac); + BREAK; + + case LC3_CON_TEC_NS_ADV: + *q_fx_exp = *q_old_fx_exp; move16(); + + /* call Noise Substitution */ + processPLCNoiseSubstitution_fx(q_d_fx, q_old_d_fx, yLen); + + BREAK; + default: ASSERT(!"Unsupported PLC method!"); + } + } + + Dyn_Mem_Deluxe_Out(); +} + + diff --git a/lib_lc3plus/plc_classify_fx.c b/lib_lc3plus/plc_classify_fx.c new file mode 100644 index 000000000..bbb01826a --- /dev/null +++ b/lib_lc3plus/plc_classify_fx.c @@ -0,0 +1,424 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +#ifdef CR8_A_PLC_FADEOUT_TUNING + +static Word32 change_bit_at_position(Word32 value, Word8 bit_position, UWord8 bit) +{ + Word32 helper_mask = ~L_shl_pos(1, bit_position); + Word32 tmp = L_and(value, helper_mask); + tmp = L_or(tmp, L_shl_pos(bit, bit_position)); + return tmp; +} + +static void update_bit_and_byte_positions(Word16 longterm_analysis_counter_max_bytebuffer, Word8 *byte_position, Word8 *bit_position) +{ +#ifdef CR11_A_FIX_IN_PLC_LONGTERM_STATISTIC + IF (sub(*bit_position, 29) == 0) +#else + IF (sub(*bit_position, 30) == 0) +#endif + { + *bit_position = 0; move16(); + + if (sub(*byte_position, longterm_analysis_counter_max_bytebuffer) < -1) + { + *byte_position = add(*byte_position, 1); + } else { + *byte_position = 0; move16(); + } + } ELSE { + *bit_position = add(*bit_position, 1); + } +} + +static void array_insert_and_shift(Word32 *array, UWord8 value, Word16 longterm_analysis_counter_max, Word16 *overall_counter, Word8 *byte_position, Word8 *bit_position) +{ + Word32 current_byte = 0; + +#ifdef WMOPS + BASOP_sub_sub_start("PLC::array_insert_and_shift"); +#endif + + IF( overall_counter != NULL) + { + *overall_counter = s_min(add(*overall_counter, 1), longterm_analysis_counter_max); + } + + current_byte = array[*byte_position]; move16(); + current_byte = change_bit_at_position(current_byte, *bit_position, value); + array[*byte_position] = current_byte; move16(); + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} + +#ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER +static void array_calculate(Word32 *array_tdc, Word32 *array_ns, int length, Word16 *counter_tdc, Word16 *counter_ns, Word16 longterm_analysis_counter_max) +#else +static void array_calculate(Word32 *array_tdc, Word32 *array_ns, int length, Word16 *counter_tdc, Word16 *counter_ns, Word16 *counter_phecu, Word16 overall_counter, Word16 longterm_analysis_counter_max) +#endif +{ + int i, k; + Word32 current_byte_tdc = 0, current_byte_ns = 0; + Word16 counter_loc_tdc = 0, counter_loc_ns = 0, counter_tmp = 0; + +#ifdef WMOPS + BASOP_sub_sub_start("PLC::array_calculate"); +#endif + + for (i = length - 1; i >= 0; i--) + { + current_byte_tdc = array_tdc[i]; + current_byte_ns = array_ns[i]; + + for (k = 0; k < 30; k++) + { + counter_loc_tdc += ((current_byte_tdc >> k) & 1); + counter_loc_ns += ((current_byte_ns >> k) & 1); + counter_tmp++; + + /* Break from both loops if full 2s buffer has been evaluated */ + if (counter_tmp >= longterm_analysis_counter_max) + { + i = -1; + k = 30; + break; + } + } + } + + *counter_tdc = counter_loc_tdc; + *counter_ns = counter_loc_ns; + +#ifndef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + *counter_phecu = sub(sub(overall_counter, counter_loc_tdc), counter_loc_ns); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} +#endif + +static Word16 spectral_centroid_fx_lc(Word16 old_scf_q[], const Word16 *band_offsets, Word16 bands_number, Word16 frame_length, + Word16 fs_idx, Word8 *scratchBuffer +# ifdef ENABLE_HR_MODE + , Word16 hrmode +# endif + ); + +void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFramesInRow, Word16 bfi, + Word16 ltpf_mem_pitch_int, Word16 frame_length, Word16 frame_dms, Word16 fs_idx, Word16 yLen, + Word16 q_old_d_fx[], const Word16 *band_offsets, Word16 bands_number, AplcSetup *plcAd, Word8 *scratchBuffer +# ifdef ENABLE_HR_MODE + , Word16 hrmode +# endif + ) +{ + Dyn_Mem_Deluxe_In( + Word16 scQ15; + Word32 class; + ); + +#ifdef WMOPS + BASOP_sub_sub_start("PLC::processPLCclassify_fx"); +#endif + + UNUSED(yLen); + UNUSED(q_old_d_fx); + + if (plcAd) + { + plcAd->norm_corrQ15_fx = 0; move16(); + } + +#ifdef CR8_A_PLC_FADEOUT_TUNING + /* assert(bfi != 2 && "Error bfi flag value, state of fadeout cntr is affected by PartialConcealment here "); */ + /* Save statistics for 24 kHz, 48 kHz and 96 kHz */ + IF((sub(bfi, 1) == 0) || (((bfi >= 0) && (sub(bfi, 2) <= 0)) && ((sub(fs_idx, 2) == 0) || (sub(fs_idx, 4) == 0) || (sub(fs_idx, 5) == 0)))) /* note for PC bfi==2 is possible */ +#else + IF (sub(bfi, 1) == 0) +#endif + { + /* increase counter of lost-frames-in-a-row */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + IF (sub(bfi, 1) == 0) + { + *nbLostFramesInRow = add(*nbLostFramesInRow, 1); + *nbLostFramesInRow = s_min(*nbLostFramesInRow, 0x100); + } +#else + *nbLostFramesInRow = add(*nbLostFramesInRow, 1); + *nbLostFramesInRow = s_min(*nbLostFramesInRow, 0x100); +#endif + +#ifdef CR8_A_PLC_FADEOUT_TUNING + /*assert((bfi != 2) && "PartialConcealment checked vs bfi==0 can cause issues "); */ + IF ((sub(*nbLostFramesInRow, 1) == 0) || (bfi != 1) ) /* was "|| (bfi==0)" , NB only test bfi vs "1" as bfi can have the states [0(good),1(bad),2(good,partialConcealment) } */ +#else + IF (sub(*nbLostFramesInRow, 1) == 0) +#endif + { + *concealMethod = plcMeth; move16(); + + IF(sub(plcMeth, 1) == 0) + { + IF(ltpf_mem_pitch_int > 0) + { + *concealMethod = LC3_CON_TEC_TDPLC; move16(); /* TD-PLC */ + /* Calculate Features */ + + plcAd->norm_corrQ15_fx = plc_xcorr_lc_fx(plcAd->x_old_tot_fx, plcAd->max_len_pcm_plc, ltpf_mem_pitch_int, fs_idx); + scQ15 = spectral_centroid_fx_lc(plcAd->old_scf_q, band_offsets, bands_number, frame_length, + fs_idx, scratchBuffer +#ifdef ENABLE_HR_MODE + , hrmode +#endif + ); + + /* Classify */ + class = L_mult(plcAd->norm_corrQ15_fx, 7640); + class = L_mac(class, scQ15, -32768); + class = L_add_sat(class, -335020208); + + IF(class <= 0) + { +#ifdef ENABLE_HR_MODE + IF((frame_dms == 100) && (hrmode == 0)) +#else + IF(frame_dms == 100) +#endif + { + *concealMethod = LC3_CON_TEC_PHASE_ECU; move16(); /* Phase ECU selected */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#endif + } + ELSE + { +#ifndef CR9_G_PLC_NS_TDC_FIX + *concealMethod = LC3_CON_TEC_NS_ADV; move16(); /* Noise Substitution */ +#endif +#ifdef CR8_A_PLC_FADEOUT_TUNING + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#endif + } + } +#ifdef CR8_A_PLC_FADEOUT_TUNING + ELSE { + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 1, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 0, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + } +#endif + } + ELSE + { + *concealMethod = LC3_CON_TEC_NS_ADV; move16(); /* Noise Substitution */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + array_insert_and_shift(plcAd->plc_longterm_advc_tdc, 0, plcAd->longterm_analysis_counter_max, &plcAd->overall_counter, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); + array_insert_and_shift(plcAd->plc_longterm_advc_ns, 1, plcAd->longterm_analysis_counter_max, NULL, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#endif + } + +#ifdef CR8_A_PLC_FADEOUT_TUNING +# ifdef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + array_calculate(plcAd->plc_longterm_advc_tdc, plcAd->plc_longterm_advc_ns, plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_plcTdc, &plcAd->longterm_counter_plcNsAdv, plcAd->longterm_analysis_counter_max); +# else + array_calculate(plcAd->plc_longterm_advc_tdc, plcAd->plc_longterm_advc_ns, plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_plcTdc, &plcAd->longterm_counter_plcNsAdv, &plcAd->longterm_counter_plcPhaseEcu, plcAd->overall_counter, plcAd->longterm_analysis_counter_max); +# endif + update_bit_and_byte_positions(plcAd->longterm_analysis_counter_max_bytebuffer, &plcAd->longterm_counter_byte_position, &plcAd->longterm_counter_bit_position); +#endif + } + + } + } + + Dyn_Mem_Deluxe_Out(); +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} + + +Word16 spectral_centroid_fx_lc(Word16 old_scf_q[], const Word16 *band_offsets, Word16 bands_number, Word16 frame_length, + Word16 fs_idx, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif + ) +{ + Dyn_Mem_Deluxe_In( + Counter i, j; + Word32 den32, num32, tmp32; + Word16 s, sc, fac, freq, inv, startfreq, stopfreq; + Word16 s2; + Word16 *old_scf_q_mod; + Word16 *old_scf_q_mod_exp; + Word16 *band_offsets_local; + ); +#ifdef WMOPS + BASOP_sub_sub_start("PLC::spectral_centroid_fx_lc"); +#endif + +#ifdef ENABLE_HR_MODE + s2 = 0; +#else + UNUSED(s2); +#endif + + + old_scf_q_mod = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * M */ + old_scf_q_mod_exp = (Word16 *)scratchAlign(old_scf_q_mod, sizeof(*old_scf_q_mod) * M); /* Size = 2 * M */ + band_offsets_local = (Word16 *)scratchAlign(old_scf_q_mod_exp, sizeof(*old_scf_q_mod_exp) * (M)); /* Size = 2 * bands_number */ + + /* Linear Domain */ + FOR (i = 0; i < M; i++) + { + old_scf_q_mod[i] = BASOP_Util_InvLog2_16(old_scf_q[i], &old_scf_q_mod_exp[i]); + } + + /* De-emphasis */ + FOR (i = 0; i < M; i++) + { + old_scf_q_mod[i] = mult(old_scf_q_mod[i], lpc_warp_dee_emphasis[fs_idx][i]); move16(); + old_scf_q_mod_exp[i] = add(old_scf_q_mod_exp[i], lpc_warp_dee_emphasis_e[fs_idx][i]); move16(); + } + + IF (sub(bands_number, 64) == 0) + { + basop_memmove(band_offsets_local, band_offsets, (bands_number + 1) * sizeof(Word16)); + } + IF (sub(bands_number, 32) < 0) + { + band_offsets_local[0] = 0; move16(); + s = sub(32, bands_number); + FOR (i = sub(bands_number, 1); i >= s; i--) + { + band_offsets_local[(i + s) * 2 + 1 + 1] = band_offsets[i + 1]; move16(); + band_offsets_local[(i + s) * 2 + 0 + 1] = band_offsets[i + 1]; move16(); + } + FOR (i = sub(s, 1); i >= 0; i--) + { + band_offsets_local[i * 4 + 3 + 1] = band_offsets[i + 1]; move16(); + band_offsets_local[i * 4 + 2 + 1] = band_offsets[i + 1]; move16(); + band_offsets_local[i * 4 + 1 + 1] = band_offsets[i + 1]; move16(); + band_offsets_local[i * 4 + 0 + 1] = band_offsets[i + 1]; move16(); + } + } + ELSE + IF (sub(bands_number, 64) < 0) + { + band_offsets_local[0] = 0; move16(); + s = sub(64, bands_number); + FOR (i = sub(bands_number, 1); i >= s; i--) + { + band_offsets_local[i + s + 1] = band_offsets[i + 1]; move16(); + } + FOR (i = sub(s, 1); i >= 0; i--) + { + band_offsets_local[i * 2 + 1 + 1] = band_offsets[i + 1]; move16(); + band_offsets_local[i * 2 + 0 + 1] = band_offsets[i + 1]; move16(); + } + } + + den32 = 1; move16(); + num32 = 0; move16(); + inv = div_s(1, frame_length); + + FOR (i = 0; i < M; i++) + { + freq = 0; move16(); + startfreq = add(band_offsets_local[i * 4], 1); + stopfreq = band_offsets_local[i * 4 + 4]; + +# ifdef ENABLE_HR_MODE + IF (hrmode != 0) + { + tmp32 = 0; move32(); + FOR (j = startfreq; j <= stopfreq; j++) + { + tmp32 = L_add(tmp32, j); + } + + s2 = norm_l(tmp32); + freq = extract_h(L_shl(tmp32, s2)); + s2 = sub(add(15, s2), 31); + tmp32 = L_mult(inv, freq); + s = norm_l(tmp32); + } + ELSE +# endif + { + FOR (j = startfreq; j <= stopfreq; j++) + { + freq = add(freq, j); + } + + tmp32 = L_mult(inv, freq); + s = norm_l(tmp32); + } + + tmp32 = L_mult(old_scf_q_mod[i], extract_h(L_shl(tmp32, s))); + +# ifdef ENABLE_HR_MODE + if (hrmode != 0) + { + s = add(s, s2); + } +# endif + + num32 = L_add(num32, L_shl(tmp32, add(add(-15, old_scf_q_mod_exp[i]), sub(15, s)))); + den32 = L_add(den32, L_shl(L_mult(old_scf_q_mod[i], stopfreq - startfreq + 1), old_scf_q_mod_exp[i])); + } + + s = norm_l(den32); + s = sub(16, s); + + sc = div_s(extract_l(L_shr(num32, s)), extract_l(L_shr(den32, s))); + + SWITCH (fs_idx) + { + case 0: + fac = 5461; move16(); + BREAK; + case 1: + fac = 10922; move16(); + BREAK; + case 2: + fac = 16384; move16(); + BREAK; + case 3: + fac = 21845; move16(); + BREAK; + default: /* case 4: */ + fac = 32767; move16(); + BREAK; + } + sc = round_fx(L_mult(sc, fac)); +# ifdef ENABLE_HR_MODE + if (sub(fs_idx, 5) == 0) + { + sc = shl_pos(sc, 1); + } +# endif + + Dyn_Mem_Deluxe_Out(); +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return sc; +} + + diff --git a/lib_lc3plus/plc_damping_scrambling_fx.c b/lib_lc3plus/plc_damping_scrambling_fx.c new file mode 100644 index 000000000..4c5641634 --- /dev/null +++ b/lib_lc3plus/plc_damping_scrambling_fx.c @@ -0,0 +1,430 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processPLCDampingScrambling_main_fx(Word16 bfi, Word16 concealMethod, Word16 ns_nbLostFramesInRow, Word16 *cum_fflcAtten, + Word16 pc_nbLostFramesInRow, Word16 *ns_seed, Word16 *pc_seed, Word16 pitch_present_bfi1, + Word16 pitch_present_bfi2, Word32 spec[], Word16 *q_fx_exp, Word16 *q_old_d_fx, + Word16 *q_old_fx_exp, Word16 L_spec, Word16 stabFac, Word16 frame_dms, + Word16 *cum_fading_slow, Word16 *cum_fading_fast, Word16 spec_inv_idx +#ifdef CR8_A_PLC_FADEOUT_TUNING + , UWord8 plc_fadeout_type +#endif + ) +{ + Dyn_Mem_Deluxe_In( + Word16 processDampScramb; + ); + + IF ( bfi != 0 ) + { + processDampScramb = 0; move16(); + test(); + IF (sub(concealMethod, LC3_CON_TEC_NS_ADV) == 0 || sub(bfi, 2) == 0) + { + processDampScramb = 1; move16(); + } + +#ifdef CR8_A_PLC_FADEOUT_TUNING + IF (sub(ns_nbLostFramesInRow, 1) == 0) + { + *cum_fading_slow = 32767; move16(); + *cum_fading_fast = 32767; move16(); + *cum_fflcAtten = 32767; move16(); + } +#endif + + IF (sub(bfi, 1) == 0) + { + processPLCDampingScrambling_fx(spec, L_spec, ns_nbLostFramesInRow, stabFac, + processDampScramb, cum_fflcAtten, + pitch_present_bfi1, frame_dms, cum_fading_slow, + cum_fading_fast, ns_seed, 0 +#ifdef CR8_A_PLC_FADEOUT_TUNING + , plc_fadeout_type +#endif + ); + } + ELSE /* bfi == 2 */ + { + processPLCDampingScrambling_fx(spec, L_spec, pc_nbLostFramesInRow, stabFac, + processDampScramb, cum_fflcAtten, + pitch_present_bfi2, frame_dms, cum_fading_slow, + cum_fading_fast, pc_seed, spec_inv_idx +#ifdef CR8_A_PLC_FADEOUT_TUNING + , plc_fadeout_type +#endif + ); + + processPLCupdateSpec_fx(q_old_d_fx, q_old_fx_exp, spec, q_fx_exp, L_spec); + } + } + Dyn_Mem_Deluxe_Out(); +} + +void processPLCDampingScrambling_fx(Word32 spec[], Word16 L_spec, Word16 nbLostFramesInRow, Word16 stabFac, Word16 processDampScramb, + Word16 *cum_fflcAtten, Word16 pitch_present, Word16 frame_dms, Word16 *cum_fading_slow, + Word16 *cum_fading_fast, Word16 *seed, Word16 spec_inv_idx +#ifdef CR8_A_PLC_FADEOUT_TUNING + , UWord8 plc_fadeout_type +#endif + ) +{ + Counter i; + Word16 lossDuration_dms, slow, fast, tmp16; + Word16 plc_start_inFrames, plc_end_inFrames, plc_duration_inFrames, linFuncStartStop; + Word16 randThreshold, ad_threshFac, energThreshold, s, s2, s3, mean_energy16; + Word32 frame_energy, mean_nrg, fac; + Word16 fflcAtten, cum_fading_slow_local, cum_fading_fast_local; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processPLCDampingScrambling_fx", sizeof(struct { + Counter i; + Word16 lossDuration_dms, slow, fast, tmp16; + Word16 plc_start_inFrames, plc_end_inFrames, plc_duration_inFrames, linFuncStartStop; + Word16 randThreshold, ad_threshFac, energThreshold, s, s2, s3, mean_energy16; + Word32 frame_energy, mean_nrg, fac; + Word16 fflcAtten, cum_fading_slow_local, cum_fading_fast_local; + })); +#endif + + /** preparation */ +#ifndef CR8_A_PLC_FADEOUT_TUNING + /* init cummulative damping factors at first loss */ + IF (sub(nbLostFramesInRow, 1) == 0) + { + *cum_fading_slow = 32767; move16(); + *cum_fading_fast = 32767; move16(); + *cum_fflcAtten = 32767; move16(); + } +#endif + + /* get damping factors */ + tmp16 = mult(6554 /*0.2*/, stabFac); + slow = add(26214 /*0.8*/, tmp16); + fast = add( 9830 /*0.3*/, tmp16); + + + SWITCH (frame_dms) + { + case 25: + IF (sub(slow, 32767) < 0) + { + tmp16 = 0; + slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = shl(slow, tmp16); + } + IF (sub(slow, 32767) < 0) + { + tmp16 = 0; + slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = shl(slow, tmp16); + } + IF (sub(fast, 32767) < 0) + { + tmp16 = 0; + fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = shl(fast, tmp16); + } + IF (sub(fast, 32767) < 0) + { + tmp16 = 0; + fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = shl(fast, tmp16); + } + BREAK; + case 50: + IF (sub(slow, 32767) < 0) + { + tmp16 = 0; + slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = shl(slow, tmp16); + } + IF (sub(fast, 32767) < 0) + { + tmp16 = 0; + fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = shl(fast, tmp16); + } + BREAK; +#ifdef ENABLE_075_DMS_MODE +# ifdef CR8_G_ADD_75MS + case 75: + IF (sub(slow, 32767) < 0) + { + slow = mult(slow, mult(slow, slow)); + } + IF (sub(slow, 32767) < 0) + { + tmp16 = 0; + slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = shl(slow, tmp16); + } + IF (sub(slow, 32767) < 0) + { + tmp16 = 0; + slow = Sqrt16_lc3plus(slow, &tmp16); move16(); + slow = shl(slow, tmp16); + } + IF (sub(fast, 32767) < 0) + { + fast = mult(fast, mult(fast, fast)); + } + IF (sub(fast, 32767) < 0) + { + tmp16 = 0; + fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = shl(fast, tmp16); + } + IF (sub(fast, 32767) < 0) + { + tmp16 = 0; + fast = Sqrt16_lc3plus(fast, &tmp16); move16(); + fast = shl(fast, tmp16); + } + BREAK; +# endif +#endif + } + +#ifdef CR8_A_PLC_FADEOUT_TUNING + if (plc_fadeout_type == 0) + { +#endif + *cum_fading_slow = mult_r(*cum_fading_slow, slow); + *cum_fading_fast = mult_r(*cum_fading_fast, fast); +#ifdef CR8_A_PLC_FADEOUT_TUNING + } +#endif + + IF ( sub(processDampScramb, 1) == 0 ) + { +#ifdef CR8_A_PLC_FADEOUT_TUNING + if (plc_fadeout_type != 0) + { + Word16 lost_frame_thr1 = 4; + Word16 lost_frame_thr2 = 8; + + SWITCH (frame_dms) + { + case 25: + lost_frame_thr1 = 16; + lost_frame_thr2 = 32; + BREAK; + case 50: + lost_frame_thr1 = 8; + lost_frame_thr2 = 16; + BREAK; +#ifdef ENABLE_075_DMS_MODE +# ifdef CR8_G_ADD_75MS + case 75: + lost_frame_thr1 = 6; + lost_frame_thr2 = 11; +# endif +#endif + } + IF (sub(nbLostFramesInRow, lost_frame_thr1) < 0) + { + cum_fading_slow_local = 32767; move16(); + } + ELSE IF (sub(nbLostFramesInRow, lost_frame_thr2) < 0) + { + cum_fading_slow_local = 29491; move16(); + } + ELSE + { + cum_fading_slow_local = 27852; move16(); + } + + *cum_fading_slow = mult_r(*cum_fading_slow, cum_fading_slow_local); move16(); + cum_fading_slow_local = *cum_fading_slow; move16(); + } else { +#endif + /** rapid fading for FFLC */ + fflcAtten = 32767; move16(); + cum_fading_slow_local = *cum_fading_slow; move16(); + cum_fading_fast_local = *cum_fading_fast; move16(); + + IF (spec_inv_idx == 0) + { + lossDuration_dms = DEPR_i_mult(nbLostFramesInRow, frame_dms); + IF (sub(lossDuration_dms, PLC_FADEOUT_IN_MS*10) > 0) + { + *cum_fflcAtten = 0; move16(); + fflcAtten = 0; move16(); + } + ELSE IF (sub(lossDuration_dms, 200) > 0) + { + SWITCH (frame_dms) + { + case 25: fflcAtten = PLC34_ATTEN_FAC_025_FX; BREAK; + case 50: fflcAtten = PLC34_ATTEN_FAC_050_FX; BREAK; +#ifdef ENABLE_075_DMS_MODE +# ifdef CR8_G_ADD_75MS + case 75: fflcAtten = PLC34_ATTEN_FAC_075_FX; BREAK; +# endif +#endif + case 100: fflcAtten = PLC34_ATTEN_FAC_100_FX; BREAK; + } + } + IF ( sub(fflcAtten, 32767) < 0 ) + { + *cum_fflcAtten = mult_r(*cum_fflcAtten, fflcAtten); + cum_fading_slow_local = mult_r(*cum_fading_slow, *cum_fflcAtten); + cum_fading_fast_local = mult_r(*cum_fading_fast, *cum_fflcAtten); + } + } + + /** prepare fade-out function */ + /* being 1 up to plc_start_inFrames, being 0 starting with + plc_end_inFrames; decreasing linearly in between */ + SWITCH (frame_dms) + { + case 25: + plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 25; move16(); + plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 25; move16(); + BREAK; + case 50: + plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 50; move16(); + plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 50; move16(); + BREAK; +#ifdef ENABLE_075_DMS_MODE +# ifdef CR8_G_ADD_75MS + case 75: + plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 75; move16(); + plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 75; move16(); + BREAK; +# endif +#endif + default: + plc_start_inFrames = (10*PLC4_TRANSIT_START_IN_MS) / 100; move16(); + plc_end_inFrames = (10*PLC4_TRANSIT_END_IN_MS) / 100; move16(); + } + + if (pitch_present == 0) + { + plc_start_inFrames = 1; move16(); + } + plc_duration_inFrames = sub(plc_end_inFrames, plc_start_inFrames); + + IF (sub(nbLostFramesInRow, plc_start_inFrames) <= 0) + { + linFuncStartStop = 32767; move16(); + } + ELSE IF (sub(nbLostFramesInRow, plc_end_inFrames) >= 0) + { + linFuncStartStop = 0; move16(); + } + ELSE + { + /* + x = xLostFramesInRow; + m = -1 / plc_duration_inFrames; + b = -plc_end_inFrames; % shift on x axis + linFuncStartStop = m * (x + b); + */ + linFuncStartStop = div_s(sub(plc_end_inFrames, nbLostFramesInRow), plc_duration_inFrames); + } + + /** sign scrambling */ + randThreshold = mult(-32768, linFuncStartStop); +#ifdef CR8_A_PLC_FADEOUT_TUNING + } +#endif + + tmp16 = *seed; move16(); + FOR (i = spec_inv_idx; i < L_spec; i++) + { + tmp16 = extract_l(L_mac0(16831, tmp16, 12821)); + + IF (tmp16 < 0) + { + test(); +#ifdef CR8_A_PLC_FADEOUT_TUNING + if (plc_fadeout_type != 0 || pitch_present == 0 || sub(tmp16, randThreshold) < 0 ) +#else + if (pitch_present == 0 || sub(tmp16, randThreshold) < 0) +#endif + { + spec[i] = L_negate(spec[i]); + } + } + + } + *seed = tmp16; move16(); + +#ifdef CR8_A_PLC_FADEOUT_TUNING + if (plc_fadeout_type == 0) + { +#endif + /** adaptive damping */ + tmp16 = mult(18022 /* 10 - 1.2 */, linFuncStartStop); + ad_threshFac = add(shr(tmp16, 1), 1228 /* 1.2 >> 1 */); /* exp = 5 */ + + s = getScaleFactor32_lc3plus(&spec[spec_inv_idx], sub(L_spec, spec_inv_idx)); + frame_energy = 0; move32(); + FOR (i = spec_inv_idx; i < L_spec; i++) + { + tmp16 = extract_h(L_shl_sat(spec[i], sub(s, 4))); + frame_energy = L_mac0(frame_energy, tmp16, tmp16); /* exp = -(2*(s-16) - 8) */ + } + mean_energy16 = BASOP_Util_Divide3216_Scale_lc3plus(frame_energy, sub(L_spec, spec_inv_idx), &s2); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) */ + + energThreshold = mult(ad_threshFac, mean_energy16); /* exp = -(2*(s-16) - 8) + 16 - (15-s2) + 5 */ + + s3 = add(sub(29, shl(sub(s, 16), 1)), s2); + IF (sub(energThreshold, 32767) < 0) + { + energThreshold = Sqrt16_lc3plus(energThreshold, &s3); + } + s3 = sub(s3, 15); + + mean_nrg = L_shl_sat(L_deposit_l(energThreshold), s3); /* exp = 0 */ + fac = mult(sub(cum_fading_slow_local, cum_fading_fast_local), energThreshold); + fac = L_shl_sat(L_deposit_l(fac), s3); /* exp = 0 */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + } +#endif + + FOR (i = spec_inv_idx; i < L_spec; i++) + { +#ifdef CR8_A_PLC_FADEOUT_TUNING + if ( ( plc_fadeout_type != 0 ) || (L_sub(L_abs(spec[i]), mean_nrg) < 0) ) +#else + if (L_sub(L_abs(spec[i]), mean_nrg) < 0) +#endif + { + spec[i] = Mpy_32_16_lc3plus(spec[i], cum_fading_slow_local); + } + else + { + if (spec[i] > 0) + { + spec[i] = L_add_sat(Mpy_32_16_lc3plus(spec[i], cum_fading_fast_local), fac); + } + else if (spec[i] == 0) + { + spec[i] = Mpy_32_16_lc3plus(spec[i], cum_fading_fast_local); + } + else + { + spec[i] = L_sub_sat(Mpy_32_16_lc3plus(spec[i], cum_fading_fast_local), fac); + } + } + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/plc_lpc_scaling_fx.c b/lib_lc3plus/plc_lpc_scaling_fx.c new file mode 100644 index 000000000..85ffbf942 --- /dev/null +++ b/lib_lc3plus/plc_lpc_scaling_fx.c @@ -0,0 +1,36 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processPLCLpcScaling_fx(Word32 tdc_A_32[], Word16 tdc_A_16[], Word16 m) +{ + Counter i; + Word16 s; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processPLCLpcScaling_fx", sizeof(struct { + Counter i; + Word16 s; + })); +#endif + + s = getScaleFactor32_lc3plus(tdc_A_32, m); + FOR (i = 0; i < m; i++) + { + tdc_A_16[i] = round_fx_sat(L_shl_sat(tdc_A_32[i], s)); move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/plc_main_fx.c b/lib_lc3plus/plc_main_fx.c new file mode 100644 index 000000000..1948aa23a --- /dev/null +++ b/lib_lc3plus/plc_main_fx.c @@ -0,0 +1,85 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processPLCmain_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLostFramesInRow, Word16 bfi, Word16 prev_bfi, + Word16 frame_length, Word16 la_zeroes, +#ifdef ENABLE_HR_MODE + const Word32 w[], +#else + const Word16 w[], +#endif + Word16 x_fx[], Word16 ola_mem[], + Word16 *ola_mem_exp, Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], + Word16 *q_fx_exp, Word16 yLen, Word16 fs_idx, const Word16 *band_offsets, Word16 bands_number, Word16 *damping, + Word16 old_pitch_int, Word16 old_pitch_fr, Word16 *ns_cum_alpha, Word16 *ns_seed, + AplcSetup *plcAd, Word16 frame_dms, Word8 *scratchBuffer, Word16 *pc_nbLostFramesInRow +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + ,Word32 rel_pitch_change +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + ,Word16 *alpha_type_2_table +#endif +) +{ + IF(sub(bfi, 1) == 0 && plcAd) + { + /* FFLC increases the PFLC counter */ + *pc_nbLostFramesInRow = add(*pc_nbLostFramesInRow, 1); + } + + processPLCclassify_fx(plcMeth, concealMethod, nbLostFramesInRow, bfi, old_pitch_int, frame_length, frame_dms, + fs_idx, yLen, q_old_d_fx, band_offsets, bands_number, plcAd, scratchBuffer +#ifdef ENABLE_HR_MODE + , hrmode +#endif + ); + + processPLCapply_fx( +#ifdef CR8_A_PLC_FADEOUT_TUNING + concealMethod, +#else + *concealMethod, +#endif + *nbLostFramesInRow, bfi, prev_bfi, frame_length, la_zeroes, w, x_fx, ola_mem, + ola_mem_exp, q_old_d_fx, q_old_fx_exp, q_d_fx, q_fx_exp, yLen, fs_idx, damping, old_pitch_int, + old_pitch_fr, ns_cum_alpha, ns_seed, frame_dms, plcAd, scratchBuffer +#ifdef ENABLE_HR_MODE + , hrmode +#endif +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + , rel_pitch_change +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + , alpha_type_2_table +#endif + ); + + IF (bfi == 0) + { + processPLCupdateSpec_fx(q_old_d_fx, q_old_fx_exp, q_d_fx, q_fx_exp, yLen); + } + +#ifdef ENABLE_HR_MODE + IF (plcAd != NULL && (sub(plcAd->PhECU_frame_ms , 10) == 0) && (hrmode == 0)) +#else + IF (plcAd != NULL && (sub(plcAd->PhECU_frame_ms , 10) == 0)) +#endif + { + processPLCspec2shape_fx(prev_bfi, bfi, q_old_d_fx, yLen, plcAd->PhECU_oold_grp_shape_fx, plcAd->PhECU_old_grp_shape_fx); + } + +} + + diff --git a/lib_lc3plus/plc_noise_substitution_fx.c b/lib_lc3plus/plc_noise_substitution_fx.c new file mode 100644 index 000000000..ab618ae7e --- /dev/null +++ b/lib_lc3plus/plc_noise_substitution_fx.c @@ -0,0 +1,32 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processPLCNoiseSubstitution_fx(Word32 spec[], Word16 spec_prev[], Word16 L_spec) +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + + FOR (i = 0; i < L_spec; i++) + { + spec[i] = L_deposit_h(spec_prev[i]); + } + + /* High pass to prevent overflows */ + spec[0] = Mpy_32_16_lc3plus(spec[0], 6553 /* 0.2 Q15*/); move32(); + spec[1] = Mpy_32_16_lc3plus(spec[1], 16384 /* 0.5 Q15*/); move32(); + + Dyn_Mem_Deluxe_Out(); +} + + + diff --git a/lib_lc3plus/plc_phecu_f0_refine_first_fx.c b/lib_lc3plus/plc_phecu_f0_refine_first_fx.c new file mode 100644 index 000000000..5c01a0029 --- /dev/null +++ b/lib_lc3plus/plc_phecu_f0_refine_first_fx.c @@ -0,0 +1,100 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void plc_phEcu_F0_refine_first_fx(Word16 * plocs, /* i/o */ + const Word16 n_plocs_in, Word32 *L_f0est, /* i/o Q16 */ + const Word16 stPhECU_f0hzLtpBinQ7, const Word16 stPhECU_f0gainLtpQ15, + const Word16 nSubm) + +{ + Counter subm, i; + Word16 ploc, n_plocs_ana; + Word32 L_tmp = 0, L_diff, L_f0EstQ7, L_sensitivity_Q7; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("plc_phEcu_F0_refine_first_fx", sizeof(struct { + Counter subm, i; + Word16 ploc, n_plocs_ana; + Word32 L_tmp, L_diff, L_f0EstQ7, L_sensitivity_Q7; + })); +#endif + + + + /* single initial peak F0 correction using available LTP information */ + + IF (sub(stPhECU_f0gainLtpQ15, ((Word16)(0.25 * 32768.0))) > 0) + { + ploc = -1; move16(); /* sentinel */ + n_plocs_ana = s_min(n_plocs_in, 4); /* only analyze at first 3 deteteced LF peaks */ + + /* only apply analysis below nsubm*pitmax_freq ~= 1600Hz */ + i = sub(n_plocs_ana, 1); + WHILE (i >= 0 && sub(plocs[i], (Word16)(1600.0 / 62.5)) > 0) + { + i--; + } + n_plocs_ana = add(i, 1); + + IF ((n_plocs_ana > 0)) + { + /* % find/correct first peak in f0est , that is a submultiple of n*f0Ltp*/ + FOR (i = 0; i < n_plocs_ana; i++) + { + + L_sensitivity_Q7 = L_deposit_l(((Word32)1) << (7 - 1)); /* 0.5 in Q7 */ + if (sub(stPhECU_f0gainLtpQ15, ((Word16)(0.75 * 32768.0))) < 0) + { + L_sensitivity_Q7 = L_shr_pos(L_sensitivity_Q7, 1); /* % more picky if correlation is rather low */ + } + + L_f0EstQ7 = L_shr_pos(L_f0est[i], 9); /* Q16 to Q7 */ + + FOR (subm = 1; subm <= nSubm; subm++) + { + /*adjf0 = abs(f0est - subm*stPhECU_f0hzLtpBin*ones(size(f0est))) < sensitivity ; % L1 difference, + vector operation over f0 + ind = find(adjf0==1,1); */ + L_diff = L_msu0(L_f0EstQ7, subm, stPhECU_f0hzLtpBinQ7); + L_diff = L_abs(L_diff); + IF (L_sub(L_diff, L_sensitivity_Q7) < 0) + { + L_tmp = L_shl_pos(L_mult0(subm, stPhECU_f0hzLtpBinQ7), 16 - 7); /* to Q16 */ + ploc = i; move16(); + BREAK; + } + L_sensitivity_Q7 = Mpy_32_16_lc3plus(L_sensitivity_Q7, (Word16)(0.875 * 32768.0 )); /* 2 cycles */ + } /* subm*/ + + IF (ploc >= 0) + { + BREAK; + } + } /* i, n_ploc_ana*/ + } + + if (ploc >= 0) + { + L_f0est[ploc] = L_tmp; move32(); /* in Q16 */ + /*ideally also integer plocs should be updated , e.g. if f0est goes from 1.45(plocs=1) to 1.6(plocs==2) + */ + /* but that is costly and not required as long as corr_phase width is large enough ]*/ + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + +} + + diff --git a/lib_lc3plus/plc_phecu_fec_hq_fx.c b/lib_lc3plus/plc_phecu_fec_hq_fx.c new file mode 100644 index 000000000..ca2a345f4 --- /dev/null +++ b/lib_lc3plus/plc_phecu_fec_hq_fx.c @@ -0,0 +1,3157 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" +#include "math.h" /*dbg*/ + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define DELTA_CORR 5 /* Tuning parameter - defining range for phase correction around peak */ +#define DELTA_CORR_F0_INT 2 /* Tuning parameter - defining range for phase correction around peak */ + +#define MAX_INCREASE_GRPPOW_FX 0 /* max. amplification in case of transients (in dB scale) */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING +# define ONE_SIDED_SINE_WIDTH (4) /* expected pure sine main lobe maximum width (4+1+4) bins *62.5 hz/bin => approx 560 Hz total width */ +# define SIDE_LIM 12539859L /* 10^ (4.5/20.0) = 2^(a); --> x= 0.747433821 -> Lx_Q24 = round((1L<<(24))*0.747433821)) = 12539859 */ +# define LFHF_LIM 16719812L /* 10^ (6.0/20.0) = 2^(b); --> x= 0.996578428 -> Lx_Q24 = round((1L<<(24))*0.996578428)) = 16719812 */ +#endif + +#ifdef CR8_A_PLC_FADEOUT_TUNING +#else + +#if PLC2_FADEOUT_IN_MS == 0 +#define BURST_ATT_THRESH (4) /* speech start attenuate with losses in a row , stable content is +1 */ +#define ATT_PER_FRAME 2 /* ptr to a table , regular voiced attenuation settings table [0.4 dBx16 frames + 6dBx16 frames] 10 ms frame */ +/* #define ATT_PER_FRAME 1 */ /* ptr to a table , regular attenuation settings table [0.3 dBx16 frames + 6dBx16 frames] 10 ms frame */ +#define BETA_MUTE_THR 20 /* time threshold from BFI start to start of beta-noise further energy attenuation, by .5 each frame */ +/* #define OFF_FRAMES_LIMIT 30 in defines.h , table size and complete zero signal after BURST_ATT_THRESH + OFF_FRAMES_LIMIT */ +#endif + +#if PLC2_FADEOUT_IN_MS != 0 /* TD_PLC muting setting */ + /*% burst attenuation scheme is allowed to be indirectly controlled by a setting from TDC-PLC settings ,if negative PLC2_FADEOUT_IN_MS */ + +#if (PLC2_FADEOUT_IN_MS < 0) +#define FADEOUT_IN_MS PLC_FADEOUT_IN_MS /*% use TDC-SETTING as input */ +#else +#define FADEOUT_IN_MS PLC2_FADEOUT_IN_MS /* % use a PLC2 individual settings as basis */ +#endif + + /* %Examples + % FADEOUT_IN_MS ==30 ms --> shortest setting, att per frame idx = 10 for PLC2 + % FADEOUT_IN_MS ==40 ms --> att per frame idx = 8 setting for PLC2 + % FADEOUT_IN_MS ==60 ms --> att per frame idx = 6 setting for PLC2 (3+4) low decay then fast decay + % FADEOUT_IN_MS ==80 ms --> att per frame idx = 4 setting for PLC2 + % FADEOUT_IN_MS ==100 ms --> att per frame idx = 2 longest = near original setting for PLC2 + */ +#define PLC_P800_SPEECH_FADEOUT_IN_FRAMES (FADEOUT_IN_MS/10) +#define PLC2_FADEOUT_IN_FRAMES MIN(OFF_FRAMES_LIMIT,MAX(6, (3*PLC_P800_SPEECH_FADEOUT_IN_FRAMES))) /* help variable */ + +#define BURST_ATT_THRESH_PRE MIN(5,MAX(1,((1*PLC2_FADEOUT_IN_FRAMES)/6))) /* nominal 10-50 ms to start actual muting, will be thresh +1 */ + +#undef ATT_PER_FRAME +#define ATT_PER_FRAME MIN(10, MAX(2, 2*(6-BURST_ATT_THRESH_PRE))) /* we let the BURST_ATT_THRESH_PRE control the initial table selection */ +/* will eventually become ATT_PER_FRAME-1 = */ + /* table ptr 1,2 --> 16 low decay, 16 high decay, "0" */ + /* table ptr 3,4 --> 8 low decay, 24 high decay, "0" */ + /* table ptr 5,6 --> 4 low decay, 28 high decay , "0"*/ + /* table ptr 7,8 --> 2 low decay, 30 high decay, "0"*/ + /* table ptr 9,10 --> 1 low decay, 31 high decay, "0"*/ +#undef BURST_ATT_THRESH +#define BURST_ATT_THRESH MIN(BURST_ATT_THRESH_PRE, 4 ) /* nominal 10-40 ms, of no regular muting , 20-50 ms */ + + /* beta mute starts to become active when the low decay mute has ended */ +#undef BETA_MUTE_THR +#define BETA_MUTE_THR MIN( 4+(OFF_FRAMES_LIMIT/2)+1 , MAX(4, BURST_ATT_THRESH + 1 +(1<<(BURST_ATT_THRESH_PRE-1)))) /* nominal time to start mandatory decrease of Xavg */ + +#if (ATT_PER_FRAME < 2) || (ATT_PER_FRAME > 10) +#pragma message(" ROM table POW_ATT_TABLES needs update to change the ATT_PER FRAME constants supported are (1),2 (3), 4, (5) ,6 dB/frame ") +#endif + +#else +#if ( ATT_PER_FRAME != 2) +#pragma (" ROM table POW_ATT_TABLES needs update to change the ATT_PER FRAME constants supported are (1),2 dB/frame ") +#endif +#endif + + +#endif + + +#define CMPLMNT_PLOC_SENS_FX 2294 /* (1.0 - p_locator_sens) in Q15 */ +#define FEC_HQ_ECU_ROOT2 23170 /*(0x5a83) */ /* sqrt(2) in Q14 */ +#define FEC_TWOTHIRDS_Q15 21845 /* round(2^15*2/3) */ + +static void get_sin_cosQ10opt(Word16 phase, /* Q10 0..1023 i.e. 1024=2*pi */ + Word16 *ptrSin, /* Q15 */ + Word16 *ptrCos); /* Q15 */ + +static Word16 sqrt2ndOrder(const Word16); + +void my_wtda_fx(const Word16 *new_audio, /* i : input audio to be windowed Q0 20 ms , OPT can be output as well */ + const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + Word32 * L_wtda_audio, /* o : tda audio Q16 20 ms */ + const Word16 L, Word8 *scratchBuffer); + +static void windowing_L(const Word16 *, Word32 *, const Word16 *, const Word16, const Word16); +static void windowing_ola(const Word16 *, Word16 *, const Word16 *, const Word16); +static void ola_add(const Word16 *, const Word16 *, Word16 *, const Word16); +static void intlvW32_2_flippedW16(Word32 *L_x, const Word16 numPairs, const Word16 L_prot, Word16 *x); +static void flippedW16_2_intlvW32(Word16 *x, const Word16 numPairs, const Word16 Lprot, Word32 *L_x); +static Word16 imax_fx(const Word16 *, const Word16); + + +Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F); + +static Word16 imax2_jacobsen_mag_fx(const Word16 *y_re, const Word16 *y_im, const Word16 special); +static void fft_spec2_sqrt_approx_fx(const Word16 x[], Word16 xMagSqrt[], const Word16 N); +static Word16 sqrtMagnApprox_fx(const Word16 re, const Word16 im); + +#ifdef CR8_A_PLC_FADEOUT_TUNING +static Word16 plc_phEcu_nonpure_tone_ana_fx(const Word16* plocs, const Word16 n_plocs, const Word16* X, + const Word32 *L_Xavg, /* i : Frequency group amp averages for tonal tilt analysis pref. Max upshifted */ + const Word16 Lprot, const Word16 fs_idx); +#endif + + +static void rotate_W16_fx(Word16 re_in, Word16 im_in, Word16 cosFactor, Word16 sinFactor, Word16 *re_out_ptr, + Word16 *im_out_ptr) +{ +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::rotate_W16_fx"); +#endif + *re_out_ptr = msu_r(L_mult(re_in, cosFactor), im_in, sinFactor); /* 2 ops no move when inlined */ + *im_out_ptr = mac_r(L_mult(re_in, sinFactor), im_in, cosFactor); /* 2 ops no move when inlined */ +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return; +} + +static void valley_magnitude_adj_fx(Word16 *re_ptr, Word16 *im_ptr, Word16 uniFactor, Word16 cosFactor) +{ + Word16 scale_fx; +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::valley_magnitude_adj_fx"); +#endif + + /* y = 0.5*((2*rand(1,10000) + 1*cos(2*pi*x)) - 1 */ /* y will be in -1 to 1 range */ + /* y = 1*((1*rand(1,10000) + 0.5*cos(2*pi*x)) - 1 */ /* y will be in -1 to 1 range */ + + scale_fx /*Q15*/ = mac_r(L_mult(uniFactor, 16384), cosFactor, 16384); + /* make gain distribution more like N(0,1) than uniform */ + + scale_fx /*Q14*/ = round_fx(L_mac((Word32)(16384L << 16), scale_fx, 4096)); + /* create a random gain scaling value with mean 1.0 and max 1.25 and min 0.75 */ + ASSERT(scale_fx <= (16384 + 8192)); + ASSERT(scale_fx >= (-16384 - 8192)); + *re_ptr = mult_r(scale_fx, shl_sat(*re_ptr, 1)); /* no moves , should be inlined */ + *im_ptr = mult_r(scale_fx, shl_sat(*im_ptr, 1)); /* no moves , should be inlined */ + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return; +} + +/*------------------------------------------------------------------* + * rand_phase() + * + * randomized phase in form of sin and cos components + *------------------------------------------------------------------*/ +Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F) +{ + /* 4x8+8 lookup scheme requiring ~40 Words of ROM freqRes 90/8 = 11.25 degrees */ + + /* x=(0:(5*8-1))*(2*pi)/32; y=sin(x);y_int=max(-32768,min(32767,round(y*32768))), y_int/32768 */ + + const Word16 *sincos_lowres_tab_cosQ15_fx = sincos_lowres_tab_sinQ15_fx + 8; + /* position at 90 degrees , ptr init */ + Word16 seed2; + Word16 seed2_shift; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("rand_phase_fx", sizeof(struct { + const Word16 *sincos_lowres_tab_cosQ15_fx; /* position at 90 degrees */ + Word16 seed2; /* 16 bit signed */ + Word16 seed2_shift; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::rand_phase_fx"); +#endif + + seed2 = extract_l(L_mac0(13849, seed, 31821)); + seed2_shift = lshr(seed2, 11); + /* logical shift to get uniform random 5 msb bits; 0-31 , 0 degrees to 31*360/32= 348.75 */ + *sin_F = sincos_lowres_tab_sinQ15_fx[seed2_shift]; move16(); /* these moves can often be avoided by returning seed2shift and inlining */ + *cos_F = sincos_lowres_tab_cosQ15_fx[seed2_shift]; move16(); /* these moves can often be avoided by inlining */ +/* total WC 5 ops */ +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return seed2; +} + +/*----------------------------------------------------------------------------- + * trans_burst_ana_fx() + * + * Transient analysis + *----------------------------------------------------------------------------*/ +void trans_burst_ana_fx( + const Word16 *xfp, /* i : Input signal (, only used if time_offset==0) now in up_scaled *Q_spec */ + Word16 * mag_chg, /* o : Magnitude modification vector Q15 */ + Word16 * ph_dith, /* o : Phase dither, 2*PI is not included (Q15, i.e., between 0.0 and 1.0) */ + Word16 * mag_chg_1st, /* i/o: per band magnitude modifier for transients Q15 */ + const Word16 output_frame, /* i : Frame length */ + const Word16 time_offs, /* i : Time offset (integral multiple of output_frame) */ + const Word16 est_stab_content, /* i : 0.0=dynamic ... 1.0=Stable (==st->env_stab ) */ + Word16 * alpha, /* o : Magnitude modification factors for fade to average */ + Word16 * beta, /* : Magnitude modification factors for fade to average */ + Word16 * beta_mute, /* i/o : Factor for long-term mute */ + Word16 * Xavg, /* o : Frequency group average gain to fade to in same Q as X_sav */ + Word16 Q_spec, Word32 L_oold_xfp_w_E_fx, Word16 oold_xfp_w_E_exp_fx, Word16 oold_Ltot_exp_fx, + Word16 *oold_grp_shape_fx, + + Word32 L_old_xfp_w_E_fx, Word16 old_xfp_w_E_exp_fx, Word16 old_Ltot_exp_fx, Word16 *old_grp_shape_fx, +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 fadeout, + Word32 * L_Xavg, /* full scale band amplitudes */ +#endif + Word8 *scratchBuffer /* Size = 4*4 * MAX_LTRANA + (2*4 + 1*2) * MAX_LGW + 8 */ +) +{ + Word16 att_val, attDegreeFrames; + Word32 * L_pGrPowLeft, *L_pGrPowRight; + Word32 * L_gr_pow_left, *L_gr_pow_right; + Word16 Lgw, i, k, burst_len; + Word16 man, expo; + Word16 att_always = 0; /* fixed attenuation per frequency group if set to 1 */ + Word16 oneOverFrame, roundEstMusContent, tmp16; +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 burst_att_thresh; + Word16 att_per_frame; +#else + Word16 burst_att_thresh = BURST_ATT_THRESH; + Word16 att_per_frame = ATT_PER_FRAME; +#endif + Word16 * tr_dec; + Word32 L_acc; + Word16 fs_scale; + Word16 scale_sh; + + Word32 L_oold_tmp, L_old_tmp; + Word16 oold_exp_fx, old_exp_fx; + Word16 margin_oold, margin_old; + Word16 fs_idx; + Word16 exp_diff; + Word16 Xavg_exp_fx, Xavg_mod_exp_fx; + Word16 tr_rise[MAX_LGW]; + Word16 tr_decay[MAX_LGW]; + Word16 man_in, expo_in, tmp; + Word32 L_tmp, L_tmp2; + Word16 thresh_tr_rise_lin_Q15; + Word16 thresh_tr_decay_lin_Q15; +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 beta_mute_thr; + Word16 fade_ms_ind; +#endif + +#ifdef DYNMEM_COUNT +#ifdef CR8_A_PLC_FADEOUT_TUNING + Dyn_Mem_In("trans_burst_ana_fx", sizeof(struct { + + Word16 att_val, attDegreeFrames; + Word32 * pGrPowLeft_L, *pGrPowRight_L; + Word32 * L_gr_pow_left, *L_gr_pow_right; + Word16 Lprot; + Word16 Lgw, i, k, burst_len; + Word16 man, expo; + Word16 att_always; /* fixed attenuation per frequency group if set to 1 */ + Word16 oneOverFrame, roundEstMusContent, tmp16; + + Word16 burst_att_thresh; + Word16 att_per_frame; + + Word16 * tr_dec; + UWord16 lsb; + Word32 L_acc; + Word16 fs_scale; + Word16 scale_sh; + + Word32 L_oold_tmp; + Word32 L_old_tmp; + Word16 fs_idx; + Word16 shift32; + Word16 margin_old; + Word16 margin_oold; + + Word16 Xavg_exp_fx, Xavg_mod_exp_fx; + Word16 tr_rise[MAX_LGW]; + Word16 tr_decay[MAX_LGW]; + + Word16 man_in, expo_in, tmp; + Word32 L_tmp, L_tmp2; + Word16 thresh_tr_rise_lin_Q15; + Word16 thresh_tr_decay_lin_Q15; + + Word16 beta_mute_thr; + Word16 fade_ms_ind; + })); +#else + Dyn_Mem_In("trans_burst_ana_fx", sizeof(struct { + + Word16 att_val, attDegreeFrames; + Word32 * pGrPowLeft_L, *pGrPowRight_L; + Word32 * L_gr_pow_left, *L_gr_pow_right; + Word16 Lprot; + Word16 Lgw, i, k, burst_len; + Word16 man, expo; + Word16 att_always; /* fixed attenuation per frequency group if set to 1 */ + Word16 oneOverFrame, roundEstMusContent, tmp16; + + Word16 burst_att_thresh; + Word16 att_per_frame; + + Word16 * tr_dec; + UWord16 lsb; + Word32 L_acc; + Word16 fs_scale; + Word16 scale_sh; + + Word32 L_oold_tmp; + Word32 L_old_tmp; + Word16 fs_idx; + Word16 shift32; + Word16 margin_old; + Word16 margin_oold; + + Word16 Xavg_exp_fx, Xavg_mod_exp_fx; + Word16 tr_rise[MAX_LGW]; + Word16 tr_decay[MAX_LGW]; + })); +#endif + +#endif + + UNUSED(xfp); + UNUSED(oold_xfp_w_E_exp_fx); + UNUSED(old_xfp_w_E_exp_fx); + + if (time_offs == 0) + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::trans_burst_ana_fx(1st)"); +#endif + } + else + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::trans_burst_ana_fx(N)"); +#endif + } + + fs_idx = mult(output_frame, (Word16)(32768.0 / 99.0)); /* truncation needed , i.e no rounding can be applied here */ + ASSERT(fs_idx == (output_frame / 100)); + + L_gr_pow_left = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LGW */ /* Size = 4 * MAX_LGW */ + + L_gr_pow_right = (Word32 *)scratchAlign(L_gr_pow_left, sizeof(*L_gr_pow_left) * MAX_LGW); /* Size = 4 * MAX_LGW */ + + tr_dec = (Word16 *)scratchAlign(L_gr_pow_right, sizeof(*L_gr_pow_right) * MAX_LGW); /* Size = 2bytes * MAX_LGW */ + + oneOverFrame = oneOverFrameQ15Tab[fs_idx]; + Lgw = s_min(add(fs_idx, LGW8K), LGW48K); /* 4,5,6,7, (7/8) */ + + burst_len = add(mult_r(time_offs, oneOverFrame), 1); + + UNUSED(est_stab_content); + UNUSED(roundEstMusContent); +#ifndef CR8_A_PLC_FADEOUT_TUNING + burst_att_thresh = add(BURST_ATT_THRESH, 1); /* in Q0 , stable setting */ + att_per_frame = sub(ATT_PER_FRAME, 1); /* in Q0 , stable setting */ +#endif + +#ifdef CR8_A_PLC_FADEOUT_TUNING + move16(); + fade_ms_ind = (PLC2_FADEOUT_IN_MS - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES; /* a shorter fading entry in fade_scheme_tab_fx */ + test(); + if (fadeout != 0) + { + fade_ms_ind = (PLC2_FADEOUT_LONG_IN_MS - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES; move16(); + /* a long fading table entry in fade_scheme_tab */ + } + + move16(); move16(); move16(); + att_per_frame = fade_scheme_tab_fx[fade_ms_ind][0]; + burst_att_thresh = fade_scheme_tab_fx[fade_ms_ind][1]; /* number of 1.0 frames before muting phase */ + /* band gain muting can take place earlier due to a band transient */ + beta_mute_thr = fade_scheme_tab_fx[fade_ms_ind][2]; /* faster muting of added noise starts when slow main signal fadeout is over */ +#endif + + + + +#ifdef PLC_FADEOUT_IN_MS +#ifdef CR8_A_PLC_FADEOUT_TUNING + ASSERT(att_per_frame >= 1 && att_per_frame <= 12); /* table based lookup restriction */ +#else + ASSERT(att_per_frame >= 1 && att_per_frame <=10 ); /* table based lookup restriction */ +#endif +#else + ASSERT(att_per_frame == 1 || att_per_frame == 2); /* table based lookup restriction */ +#endif + + *ph_dith = 0; /* peak scrambling, not in use */ + + attDegreeFrames = 0; move16(); + IF(sub(burst_len, burst_att_thresh) > 0) + { + att_always = 1; move16(); + /* increase degree of attenuation */ + + /* N.B. To facilitate the subsequent 10^(-att_degree/20) implementation + * so as to use direct table-lookup, + * the first (burstLen - burst_att_thresh) are NOT multiplied by "att_per_frame". */ + attDegreeFrames = sub(burst_len, burst_att_thresh); /* multiplied by 1.0 , */ + /* Furthermore, in order to minimize the size of the lookup-table required to + * implement 10^(-att_degree/10), hard limit attDegreeFrames to (30% of 100)=30. + * If attDegreeFrames is greater than 30, it means there are more than 30 successive + * bad frames. */ + if (sub(attDegreeFrames, OFF_FRAMES_LIMIT) > 0) + {/* Hard limit the no. of frames, for table lookup */ + attDegreeFrames = OFF_FRAMES_LIMIT; move16(); + } + } + + plc_phEcu_initWord16(alpha, 32767, MAX_LGW); + basop_memset(beta, 0, (MAX_LGW) * sizeof(Word16)); + IF(sub(burst_len, 1) <= 0) + { + *beta_mute = BETA_MUTE_FAC_INI; move16(); + *beta_mute = shr_pos(*beta_mute , 1); /* perceptual decrease */ + } + + IF(sub(burst_len, 1) <= 0) + { + L_pGrPowLeft = &L_gr_pow_left[0]; /* ptr init*/ + L_pGrPowRight = &L_gr_pow_right[0]; /* ptr init*/ + + fs_scale = xfp_wE_MDCT2FFTQ11[fs_idx]; move16(); + scale_sh = 4; /* 15-11 */ move16(); + /* L_*old_xfp_w_E_fx, always upscaled to max from the calculating function */ + + + L_oold_tmp = Mpy_32_16_lc3plus(L_oold_xfp_w_E_fx, fs_scale); + L_old_tmp = Mpy_32_16_lc3plus(L_old_xfp_w_E_fx, fs_scale); + + oold_exp_fx = add(oold_Ltot_exp_fx, scale_sh); + old_exp_fx = add(old_Ltot_exp_fx, scale_sh); + + /*re-normalize L_mantissas and adjust exps */ + margin_oold = norm_l(L_oold_tmp); + L_oold_tmp = L_shl_pos(L_oold_tmp, margin_oold); + oold_exp_fx = sub(oold_exp_fx, margin_oold); + + margin_old = norm_l(L_old_tmp); + L_old_tmp = L_shl_pos(L_old_tmp, margin_old); + old_exp_fx = sub(old_exp_fx, margin_old); + + /* now time to analyze how the actual L_tot exponent scaling should be done */ + /* bring up the lowest exp to the same exp as the higher exp, and scale down the corresponding mantissa */ + exp_diff = sub(old_exp_fx, oold_exp_fx); /* energy increase from oold to old in log2 shifts */ + + /* Overflow2 fix */ + exp_diff = s_max(-31, exp_diff); + exp_diff = s_min(31, exp_diff); + if (exp_diff > 0) + { /* oold_exp < old_exp */ + /* old_exp is limiting, shift down oold mantissa */ + L_oold_tmp = L_shr_pos(L_oold_tmp, exp_diff); + } + if (exp_diff < 0) + { /* oold_exp > old_exp */ + /* oold_exp is limiting, shift down old mantissa */ + L_old_tmp = L_shr_pos(L_old_tmp, negate(exp_diff)); + } + oold_exp_fx = s_max(oold_exp_fx, old_exp_fx); + old_exp_fx = oold_exp_fx; move16(); + + /* safety set lowest energy to 2 , as one bit is shifted away in avg calculation */ + L_oold_tmp = L_max(L_oold_tmp, 2L); + L_old_tmp = L_max(L_old_tmp, 2L); + + FOR(k = 0; k < Lgw; k++) /* NB Lgw may be shorter than all defined bands , e.g at at 48k */ + { + L_gr_pow_left[k] = Mpy_32_16_lc3plus(L_oold_tmp, oold_grp_shape_fx[k]); move32(); + L_gr_pow_right[k] = Mpy_32_16_lc3plus(L_old_tmp, old_grp_shape_fx[k]); move32(); + + /*Xavg[k] = sqrt(0.5f*(gr_pow_left[k]+gr_pow_right[k])/(float)(gw[k+1]-gw[k]));*/ + Xavg_exp_fx = sub(old_exp_fx, 1); /* virtual pre divide X_avg by 2 too keep precision in summation */ + L_acc = L_add(L_shr_pos(L_gr_pow_left[k], 1), L_shr_pos(L_gr_pow_right[k], 1)); + L_acc = L_shr_pos(L_acc, gw_len_inv_shift_fx[k]); /* divide by (bandwidth/2) in bins */ + + { /* new Xavg_fx calculation */ + L_acc = L_max(L_acc, 1L); + tmp = norm_l(L_acc); + Xavg_exp_fx = sub(Xavg_exp_fx, tmp); + L_acc = L_shl_pos(L_acc, tmp); /* now between 0.5 an 1.0*/ + + expo_in = add(Xavg_exp_fx, 0); + man_in = round_fx_sat(L_acc); + + /* now allow both positive and negative expos into sqrt */ + man = sqrt2ndOrder(man_in); + if (s_and(expo_in, 1) != 0) + { + man = mult_r(man, FEC_HQ_ECU_ROOT2); /* odd exp operation */ /* 1/sqrt(2) */ + } + expo = shr_r(expo_in, 1); /* apply even part of exp , square root operation. shr_r needed for positive side exps */ + + + + L_acc = L_deposit_h(man); + Xavg_exp_fx = add(expo, 0); + /*Note: sqrt approximaton may overshoot e.g- sqrt(1.0) may become 1.0001 i.e. saturation is needed when eventually applying expo */ + + + /* Xavg (unscaled flt in L_acc*2^(exp-31)) needs to be saved in the same scale + Q as the stored 16bit + * Xsav_fx, for use in subst_spec() */ + /* move Xavg fft scale to fx domain fx-fft scale*/ + L_acc = Mpy_32_16_lc3plus(L_acc, PhEcu_Xsav_Flt2FxScaleQ15[fs_idx]); /* fs fixed fractional change */ + Xavg_mod_exp_fx = sub(Xavg_exp_fx, PhEcu_Xsav_Flt2FxDnShift[fs_idx]); /* fs fixed exp change*/ + Xavg_mod_exp_fx = add(Xavg_mod_exp_fx, Q_spec); /* signal adaptive exp change*/ + + /* :: move to Q_spec domain of Xsav , Q fixed in first BFI frames */ + + /* extract Q0 value shift so that the mantissa is in the high part with man*2,^(0-15) */ + exp_diff = sub(15, Xavg_mod_exp_fx); + + + exp_diff = s_min(31, exp_diff); /* limit to meaningfull DSP shifts as described by up to 6 bits */ + exp_diff = s_max(-32, exp_diff); + if (exp_diff > 0) + { + L_acc = L_shr_pos(L_acc, exp_diff); /* may underflow */ + } + + if (exp_diff < 0) + { + L_acc = L_shr_sat(L_acc, exp_diff); + } +#ifdef CR8_A_PLC_FADEOUT_TUNING + L_Xavg[k] = L_acc; /* export full 31 bit scale band amplitude */ +#endif + Xavg[k] = round_fx_sat(L_acc); /* extract high part */ + + } /*end of new Xavg_fx calculation */ + /* internal transition detection */ + + { /* pure percentage based transient detection */ + thresh_tr_rise_lin_Q15 = PhEcu_frac_thr_rise_lin_Q15[k]; + thresh_tr_decay_lin_Q15 = PhEcu_frac_thr_decay_lin_Q15[k]; + + /* analyse rise */ + /* one of L_left or L_right should be pre-upshifted to a near max mantissa, (in one band ) */ + L_tmp2 = L_deposit_h(0); + L_tmp = Mpy_32_16_lc3plus(*L_pGrPowRight, thresh_tr_rise_lin_Q15); + if (L_sub(*L_pGrPowLeft, L_tmp) <= 0) + { + L_tmp2 = L_deposit_l(1); + } + + if (*L_pGrPowLeft == 0) /* denominator zero special cases */ + { + /* rise: Right/Left ; " * / 0 " --> tr_rise=1 ; "0/0" --> tr_rise = 0 */ + L_tmp2 = L_min(*L_pGrPowRight, 1L); + } + tr_rise[k] = extract_l(L_tmp2); move16(); + + /* analyse decay */ + L_tmp2 = L_deposit_h(0); + L_tmp = Mpy_32_16_lc3plus(*L_pGrPowLeft, thresh_tr_decay_lin_Q15); + if (L_sub(L_tmp, *L_pGrPowRight) >= 0) + { + L_tmp2 = L_deposit_l(1); + } + if (*L_pGrPowRight == 0) /* right side no energy , special cases */ + { + /* decay: Right/Left ; " 0 / * " --> tr_decay=0 ; "0/0" --> tr_decay = 0 */ + L_tmp2 = L_deposit_h(0); + } + tr_decay[k] = extract_l(L_tmp2); move16(); + + tr_dec[k] = s_max(tr_rise[k], tr_decay[k]); move16(); + + } /* percentage tr_dec */ + /* magnitude modification, calculated for decay only */ + IF(add(tr_dec[k], att_always) != 0) + { + +#if MAX_INCREASE_GRPPOW_FX != 0 +#error trans_burst_ana_fx-- The following implementation is incorrect +#endif + att_val = 32767; move16(); + IF(L_sub(*L_pGrPowRight, 0) > 0) + { + IF(L_sub(*L_pGrPowRight, *L_pGrPowLeft) < 0) /* decay , i.e., (gr_pow_right/gr_pow_left) < 1.0 */ + { + /* Compute sqrt(grp_pow_chg), where grp_pow_chg = gr_pow_right/gr_pow_left. */ + tmp16 = plc_phEcu_ratio_fx(*L_pGrPowRight, *L_pGrPowLeft, &expo); /* output tmp16 in Q14 */ + + expo = sub(expo, (15 - 14)); /* Now, tmp16 is considered in Q15 */ + i = norm_s(tmp16); + man = shl_pos(tmp16, i); /* Mandatory normalization before sqrtNthOrder(). */ + expo = add(expo, i); + man = sqrt2ndOrder(man); + if (s_and(expo, 1) != 0) /* Check even or odd. */ + { + man = mult_r(man, FEC_HQ_ECU_ROOT2); + } + expo = shr_pos(expo, 1); /* Divided by 2-- square root operation. */ + att_val = shr(man, expo); /* Denormalize the mantissa back to Q15. */ + } + /* ELSE + { + do nothing because (gr_pow_right/gr_pow_left) >= 1.0 + } + */ + } + + mag_chg_1st[k] = att_val; move16(); + mag_chg[k] = att_val; move16(); + } + ELSE + { + mag_chg_1st[k] = 32767; move16(); + mag_chg[k] = 32767; move16(); /* Set to ]1.0 in Q15 */ + } + + L_pGrPowLeft++; + L_pGrPowRight++; + } /* FOR band k */ + } + ELSE /* sub(burst_len, 1) <= 0) */ + { + /* BURST path */ + + /* Since attDegreeFrames is discrete (integer) and hard limited to OFF_FRAMES_LIMIT, + * it is easier to implement 10^(-att_degree/20.0) by a simply direct + * table-lookup. Also, att_per_frame is discrete as well and can be + * either ATT_PER_FRAME-1 or ATT_PER_FRAME and nothing else. This + * means only 2 tables of size=(OFF_FRAMES_LIMIT+1) each are required. + * To take square root into account, it is divided by 20 instead of 10. */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING + if (sub(burst_len, beta_mute_thr) > 0) /* beta_mute_thr coincides/close to stronger 6dB muting phase */ + { + *beta_mute = shr_pos_pos(*beta_mute, 1); + } +#endif + + + FOR(k = 0; k < Lgw; k++) /* Lgw may be shorter than all bands at 48k */ + { + /* global burst attenuation */ + #if PLC2_FADEOUT_IN_MS != 0 + #ifdef CR8_A_PLC_FADEOUT_TUNING + /* att_per_frame idx = "1:12") */ +#else + /* att_per_frame idx = "1:10") */ +#endif + att_val = POW_ATT_TABLES[att_per_frame][s_min(OFF_FRAMES_LIMIT, attDegreeFrames)]; move16(); +#else + /* att_per_frame idx = "1:2") */ + att_val = POW_ATT_TABLES[att_per_frame][s_min(OFF_FRAMES_LIMIT, attDegreeFrames)]; move16(); + /* 10^(-attDegreeFrames*(att_per_frame = "1 or 2")/20) */ +#endif + + mag_chg[k] = mult_r(mag_chg_1st[k], att_val); /* Q15 */ + +#ifndef CR8_A_PLC_FADEOUT_TUNING + if (sub(burst_len, BETA_MUTE_THR) > 0) /* BETA_MUTE_THR ~= (5+15) coincides/close to stronger 6dB muting phase */ + { + *beta_mute = shr_pos_pos(*beta_mute, 1); + } +#endif + alpha[k] = mag_chg[k]; move16(); + ASSERT(beta[k] == 0); /* initialization required */ + IF(sub(alpha[k], 32766) < 0) + { + /* beta_pre[k] = sqrt(1.0f - SQR(alpha[k])); */ + /* beta[k] = beta_pre[k]* *beta_mute;*/ + /* (1.0-alpha.^2), in exp 1 due to L_mult0; */ + + L_acc = L_sub((INT32_MAX >> 1) + 1, L_mult0(alpha[k], alpha[k])); + { + + /* use lower complex(WMOPS/ROM) 2nd-order sqrt approximation */ + Word32 L_man, L_acc2 = L_acc; + Word16 tmp, expo_in, expo2, man_in, man; + /* updated code using the 2nd order approximation routine */ + /* form is flt=(L_acc2*2.^(-31 + 1) */ + + tmp = norm_l(L_acc2); /* tmp is always 1 or higher due to Lmac0 downshift */ + man_in = round_fx_sat(L_shl_pos(L_acc2, tmp)); + expo_in = sub(1, tmp); /* 1 due to original 1 bit margin gain in L_mult0 */ + + /* both positive and negative expos into sqrt */ + man = sqrt2ndOrder(man_in); + if (s_and(expo_in, 1) != 0) + { + man = mult_r(man, FEC_HQ_ECU_ROOT2); /* odd exp operation */ /* sqrt(2)/2 */ + } + + expo2 = shr_r(expo_in, 1); /* apply square root operation. shr_r needed for pos and neg exps */ + ASSERT(expo2 <= 1); + + L_man = L_deposit_h(man); + L_man = L_shl_sat(L_man, expo2); /* move to a zero exp , _sat needed for 1.0 input (due to approximation overshoot) */ + + man = round_fx_sat(L_man); /* better perf with round here */ + + + beta[k] = mult_r(*beta_mute, man); move16(); + } + + /* bw Lowpass shape additive component */ + /* tab[LGW48K + 1] = { 1.0, ....1.0, 0.5,0.5, ... 0.1, 0.1 } */ + + IF(sub(k, LGW32K - 1) >= 0) + { + beta[k] = mult_r(beta[k], 3277); /* 0.1 in Q15 */ + } + ELSE IF(sub(k, LGW16K - 1) >= 0) + { + beta[k] = mult_r(beta[k], 16384); /* 0.5 in Q15 */ + } + + /* + % limit Xavg noise contribution further in case of offset/tr_decay + % attenuation was already active + + if (burst_len <= burst_att_thresh) && ( stPhECU_mag_chg_1st(k) < (32766/32768) ) + XavgFadeinFactor = (burst_len-1)/burst_att_thresh; + XavgFadeinFactor = min(1.0, XavgFadeinFactor); + beta(k) = beta(k)*XavgFadeinFactor; + % limit initial Xavg noise contribution until We have reached regular burst attenuation + end + end + */ + IF( sub(mag_chg_1st[k], 32767) <0 ) + { /* offset muting was started before burst muting phase */ + /* Xavg noise gradually increased during a short period */ + Word16 XavgFadeinFactor = 32767; + Word16 ratio2_3_4_5tab[4][5 - 1] = { + {(Word16)(.5 * 32768.0), (Word16)(1.0 * 32767.0), (Word16)(1.0 * 32767.0), (Word16)(1.0 * 32767.0)}, /* 1/2*/ + {(Word16)(.333 * 32768.0), (Word16)(.666 * 32768.0), (Word16)(1.0 * 32767.0), (Word16)(1.0 * 32767.0)}, /* 1/3*/ + {(Word16)(.25 * 32768.0), (Word16)(.5 * 32768.0), (Word16)(.75 * 32768.0), (Word16)(1.0 * 32767.0)}, /* 1/4 */ + {(Word16)(.2 * 32768.0), (Word16)(.4 * 32768.0), (Word16)(.6 * 32768.0), (Word16)(.8 * 32768.0)} /* 1/5 */ + + }; + ASSERT(burst_att_thresh >= 1 && burst_att_thresh <= 5); + ASSERT(burst_len >= 2); + if (sub(burst_len,burst_att_thresh) <= 0) + { + ASSERT(burst_len - 2 < (5-1)); + ASSERT(burst_att_thresh-1-1 < (4)); + XavgFadeinFactor = ratio2_3_4_5tab[burst_att_thresh-1-1][burst_len - 2]; /* second bfi frame burst_len= is 2 */ + } + beta[k] = mult_r(beta[k], XavgFadeinFactor); /* n Q15 */ + } + } /* IF (sub(alpha[k], 32766) < 0) */ + } /* FOR k*/ + + } /* BURST */ + + + + IF(sub(output_frame, L_FRAME48K) == 0) + { /* for 48kHz set/handle scalings of last group/band the same way as previous lower freq band(s) */ + + FOR(k = Lgw; k < MAX_LGW; k++) + { + tr_dec[k] = tr_dec[k - 1]; move16(); /* only available in first bfi frame */ + Xavg[k] = Xavg[k - 1]; move16(); + mag_chg_1st[k] = mag_chg_1st[k - 1]; move16(); + mag_chg[k] = mag_chg[k - 1]; move16(); + alpha[k] = alpha[k - 1]; move16(); + beta[k] = beta[k - 1]; move16(); + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} + +/*----------------------------------------------------------------------------- + * imax_fx() + * + * Get interpolated maximum position + *-----------------------------------------------------------------------------*/ +static Word16 imax_fx( /* o: The location, relative to the middle of the 3 given data point, of the maximum. (Q15) */ + const Word16 *y, /* i: The 3 given data points. */ + const Word16 special /* i: -1 = left edge special case, 0 = normal, +1 = right edge special case */ +) +{ + Word16 posi; + Word16 man, expo, edge; + const Word16 *pY; + Word32 L_y1, L_y2, L_y3, L_numer, L_denom, L_sign, L_acc, L_y3_y1; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("imax_fx", sizeof(struct { + Word16 posi; + Word16 man, expo, edge; + const Word16 *pY; + Word32 L_y1, L_y2, L_y3, L_numer, L_denom, L_sign, L_acc, L_y3_y1; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::imax_fx"); +#endif + + /* Seek the extremum of the parabola P(x) defined by 3 consecutive points + so that P([-1 0 1]) = [y1 y2 y3] */ + pY = y; + L_y1 = L_deposit_l(*pY++), L_y2 = L_deposit_l(*pY++), L_y3 = L_deposit_l(*pY); + + /* The extremum value: + * y2i = -0.125f * SQR(y3_y1) / (y1+y3-2*y2)+y2 + * is not computed. Alternatively, the derivative of the parabola evaluated at y=0, + * dP/dy|y=0, is used to determine whether the extremum is maximum or not. + */ + + /* Compute the extremum location: posi = (y3 - y1)/(4*y2 - 2*y1 - 2*y3). */ + L_y3_y1 = L_sub(L_y3, L_y1); + L_acc = L_shl_pos(L_y2, 1); /* N.B. y2 is multiplied by 2 not 4. */ + L_acc = L_sub(L_acc, L_y1); /* N.B. Y1 is not multiplied by 2. */ + L_denom = L_sub(L_acc, L_y3); /* N.B. Y3 is not multiplied by 2. */ + L_sign = L_xor(L_y3_y1, L_denom); /* Preserve the sign since div_s() only takes positive arguments. */ + L_numer = L_abs(L_y3_y1); + L_denom = L_abs(L_denom); + + test(); + IF(L_numer == 0 || L_denom == 0) + { + posi = 0; move16(); /* flat top , exit with center freq. */ + } + ELSE + { + + IF(L_sub(L_denom, L_shr_pos_pos(L_numer, 1)) > 0) + { + /* Although the output of ratio() is in Q14, adding the missing factor of 2 (See above) + * in the denominator, the output is now considered to be in Q15. */ + man = plc_phEcu_ratio_fx(L_numer, L_denom, &expo); /* The mantissa is considered in Q15 */ + + posi = shr_sat(man, expo); /* in Q15 (Due to saturation, it is automatically bound inside [-1.0,1.0].) */ + } + ELSE + { + posi = 0x7fff; move16(); + } + + if (L_sign < 0) /* Restore the sign. */ + { + posi = negate(posi); + } + + /* For both edges (left and right), the extremum found above may be minimum. + * It needs to reject the minimum. */ + IF(special != 0) /* Either edge special case. */ + { + edge = 0x7fff; /* 1 in Q15 for the right edge special case */ move16(); + if (special < 0) + { + edge = 0; /* Left edge special case */ move16(); + } + + /* The derivative (slope) of the interpolating parabola = 2*A*y + B, + * where A = (y3 + y1)/2 - y2 + * and B = (y3 - y1)/2. + * Therefore, the slope at y=0 is simply B. Use this slope to determine + * if the parabola is concave upward or downward. + */ + IF(posi > 0) /* The extremum is in between the middle and the right given data points. */ + { + posi = sub(0x7fff, posi); /* maximum case */ + if (L_sub(L_y3, L_y1) <= 0) /* Check the slope at y=0, i.e., at the middle given data point. */ + { + posi = edge; /* minimum case */ move16(); + } + } + ELSE /* The extremum is in between the left and the middle given data points. */ + { + posi = add(0x7fff, posi); /* maximum case */ + if (L_sub(L_y3, L_y1) >= 0) + { + posi = edge; /* minimum case */ move16(); + } + } + } + } +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return posi; + /* Q15. The position either left or right relative to the index of the middle of the 3 given data points. */ +} + + /*----------------------------------------------------------------------------- + * spec_ana_fx() + * + * Spectral analysis + *-----------------------------------------------------------------------------*/ + /* OPT add the FB transient input flags , and skip peakfinder if fullband transient is set */ + void spec_ana_fx(Word16 * xfp, /* i/o : Input 16ms pre-upscaled time signal, output xfp utility buffer */ + Word16 * plocs, /* o : The indicies of the identified peaks Q0 */ + Word32 * L_plocsi, /* o : Interpolated positions of the identified peaks Q16 */ + Word16 * num_plocs, /* o : Number of identified peaks Q0 */ + Word16 * X_sav, /* o : Stored fft spectrum */ + const Word16 output_frame, /* i : Frame length Q0 */ + const Word16 bwidth_fx, /* i : Encoded Fs index Q0 */ + const Word16 *sp_ana_win, /* i : spectral analysis window Q15 */ + const Word16 f0hzLtpBinQ7, /* i : LTP bin frequency in normalized Hz Q7 */ + const Word16 norm_corrQ15_fx, /* i : correlation for lag at f0hzLtpBinQ7 */ + Word16 maxLprot, Word16 maxPlocs, + Word8 *scratchBuffer /* Size = 4 * (MAX_LPROT + MAX_LPROT_RED + 1) + 2 * MAX_PLOCS */ + ) + { + Counter n, k; + Word16 nJacob, Lprot, hamm_len2 = 0, Lprot2, Lprot2p1; + Word32 *L_xfp; + + Word16 *pXfp; + Word16 *pPlocs; + Word16 Xmax, Xmin, sens; + Word16 rectLength, fraction; + Word32 *pPlocsi_L; + Word32 L_acc; + Word16 peak_range_1; + Word16 stop_band_start; + Word16 stop_band_length; + Word16 fft_scale; + Word8 * buffer_fft; + Word16 currPlocs, endPlocs; + Word16 P_in_plocs; + Word16 n_real_interp_tail; + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::spec_ana_fx(1st)"); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_In("spec_ana_fx", sizeof(struct { + Counter n, k; + Word16 nJacob ,Lprot, hamm_len2, Lprot2, Lprot2p1; + Word32 *L_xfp; + Word32 *pXfp_L; + Word16 *y_re_ptr, *y_im_ptr; /* otrs to Xsav as xfp was overwritten */ + Word16 *pXfp, *pXfp1, *pPlocs; + Word16 Xmax, Xmin, sel; + Word16 rectLength, fraction, special; + Word32 *pPlocsi_L; + Word32 L_acc; + Word16 peak_range_1; + Word16 stop_band_start; + Word16 stop_band_length; + Word16 fft_scale; + Word8 * buffer_fft; + Word16 fft_scale_by4; + Word16 currPlocs, endPlocs; + Word16 P_in_plocs; + Word16 n_real_interp_tail; + })); +#endif + /* Initialize for 48k to avoid warnings + Lprot - length of saved prototype samples + hamm_len2 - half Hamming window length + pFftTbl - Table for real input FFT + LprotLog2Minus1 - FFT stages for complex input FFT + */ + + + L_xfp = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LPROT bytes */ + buffer_fft = scratchAlign(L_xfp, sizeof(*L_xfp) * maxLprot); /* Size = 4 * (MAX_LPROT_RED + 1) + 2 * MAX_PLOCS */ + + ASSERT(bwidth_fx >= 0 && bwidth_fx <= 4); /* avoid bwidth_fx variable warning */ + + Lprot = LprotSzPtr[bwidth_fx]; + move16(); + hamm_len2 = DEPR_i_mult(3, mult(output_frame, (Word16)(3277) /* divBy10 + floor */)); /* 3 ms */ + fft_scale = PhEcuFftScale[bwidth_fx]; + move16(); /* 32,16,8 kHz all have fft scale 0, 24 has 8, 48 has 4 */ + Lprot2 = shr_pos(Lprot, 1); + Lprot2p1 = add(Lprot2, 1); /* Magnitude lengths */ + rectLength = sub(Lprot, shl_pos(hamm_len2, 1)); + /* The length of the rectangular portion of the Hamming-Rectangular window. */ + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::WhrAnaWin+fft"); +#endif + + /* Apply hamming-rect window */ + windowing_L(xfp, L_xfp, sp_ana_win, rectLength, hamm_len2); + BASOP_rfftN(L_xfp, Lprot, &fft_scale, buffer_fft); + } +#ifdef WMOPS + BASOP_sub_sub_end(); /* anawin+fft */ +#endif + + /* Convert 32 Bit intlv FFT into phecu 16 bit flipped fft format */ + /* can not yet be an inplace operation */ + + intlvW32_2_flippedW16(L_xfp, sub(Lprot2, 1), Lprot, xfp); + + /* Apply zeroing of non-coded FFT spectrum above 20 kHz */ + IF(sub(output_frame, ((L_FRAME48K) * 40) / 48) >= 0) /* only relevant for 48kHz in LC3plus */ + { + stop_band_start = ((LPROT48K / 2) * 40) / 48; /* initial start position in real part , 320 */ + stop_band_length = ((LPROT48K * 8) / 48) - 1; /* real tail and into Im parts , 128-1 */ + stop_band_start = add(stop_band_start, 1); /* exclude DC ... */ + + basop_memset(xfp + stop_band_start, 0, (stop_band_length) * sizeof(Word16)); + } + + peak_range_1 = s_min(Lprot2p1, MAX_LPROT_RED / 2 + 1); /* limit preliminary only active for 48k to save WMOPS */ + + basop_memmove(X_sav, xfp, (Lprot) * sizeof(Word16)); + + /* Magnitude representation */ + fft_spec2_sqrt_approx_fx(xfp, xfp, Lprot); + /* inplace, i.e. [ Dc, real part of xfp ,Fs/2 ] will be replaced by magnitude(scaled by .5) */ + + /* Find global maximum and minimum. */ + plc_phEcu_maxval_fx(xfp, peak_range_1, &Xmax); + plc_phEcu_minval_fx(xfp, peak_range_1, &Xmin); + sens = mult_r(sub(Xmax, Xmin), CMPLMNT_PLOC_SENS_FX); + + + plc_phEcu_peak_locator_fx(xfp, peak_range_1, plocs, num_plocs, sens, Xmax, Xmin, MAX_LPROT_RED, buffer_fft); + + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::Peaks_refine"); +#endif + + /* Refine peaks */ + pPlocsi_L = L_plocsi; + pPlocs = plocs; + /* n = sub(*num_plocs, 1); */ /* -1 so as to exclude the very last peak. */ + n = *num_plocs; /* number of peaks to process */ + /* Special case-- The very 1st peak if it is at 0 index position (DC) */ + /* With DELTA_CORR_F0_INT == 2 one needs to handle both *pPlocs==0 and *pPlocs==1 */ + logic16(); + IF((n > 0) && (sub(*pPlocs, 0) == 0)) /* Very 1st peak position possible to have a peak at 0/DC index position. */ + { + fraction = imax_fx(xfp, -1); /* -1 signifies special left edge case. */ + L_acc = L_deposit_h(*pPlocs++); /* N.B., (*pPlocs) must be zero here. */ + *pPlocsi_L++ = L_mac(L_acc, fraction, 1); move32(); /* in Q16 */ + n = sub(n, 1); /* This special case is taken care of -- one less peak to go */ + } + logic16(); + IF((n > 0) && (sub(*pPlocs, 1) == 0)) /* Also 2nd peak position uses DC which makes jacobsen unsuitable. */ + { + fraction = imax_fx(xfp, 0); /* for parabolic this is not a special case. */ + L_acc = L_deposit_h(*pPlocs++); /* N.B., (*pPlocs) must be 1 here. */ + *pPlocsi_L++ = L_mac(L_acc, fraction, 1); move32(); /* in Q16 */ + n = sub(n, 1); /* This special case is taken care of -- one less peak to go */ + } + + /* All remaining peaks except the very last two possible integer positions */ + currPlocs = *pPlocs++; move16(); + endPlocs = sub(Lprot2p1, DELTA_CORR_F0_INT); /* last *pPlocs position for Jacobsen */ + + /* precompute number of turns based on endpoint integer location and make into a proper FOR loop */ + IF(n > 0) + { + nJacob = n; move16(); + + /* catch all three xxx01 , xxx10 and xxx11 , + and not only xxx01, xxx10 */ + + n_real_interp_tail = 0; move16(); + if (sub(endPlocs, plocs[sub(*num_plocs, 1)]) <= 0) + { + n_real_interp_tail = add(n_real_interp_tail, 1); + } + + logic16(); + if (sub(n,1) > 0 && sub(endPlocs, plocs[sub(*num_plocs, 2)]) <= 0) + { + n_real_interp_tail = add(n_real_interp_tail, 1); + } + + nJacob = sub(nJacob, n_real_interp_tail); + + FOR (k = 0; k < nJacob; k++) + { + fraction = imax2_jacobsen_mag_fx(&(X_sav[currPlocs - 1]), &(X_sav[Lprot - 1 - currPlocs]), 0); /* in Q15 */ /* not endpoint */ + move16(); move16(); /* account for inloop indirect ptrs into Xsav */ + + L_acc = L_deposit_h(currPlocs); + *pPlocsi_L++ = L_mac(L_acc, fraction, 1); move32(); /* in Q16. Append the fractional part to the integral part. */ + currPlocs = *pPlocs++; move16(); + } + n = sub(n, nJacob); + } + + /* At this point there should at most two plocs left to process */ + /* the position before fs/2 and fs/2 both use the same magnitude points */ + + IF(n > 0) + { + /* [ . . . . . . . ] Lprot/2+1 positions */ + /* | | | */ + /* 0 (Lprot/2-2) (Lprot/2) */ + + pXfp = xfp + sub(Lprot2, 2); + IF(sub(currPlocs, sub(Lprot2p1, DELTA_CORR_F0_INT)) == 0) + /* Also 2nd last peak position uses fs/2 which makes jacobsen less suitable. */ + { + fraction = imax_fx(pXfp, 0); /* for parabolic this is not a special case. */ + + L_acc = L_deposit_h(currPlocs); /* N.B., (*pPlocs) must be 1 here. */ + *pPlocsi_L++ = L_mac(L_acc, fraction, 1); move32(); /* in Q16 */ + currPlocs = *pPlocs++; move16(); + n = sub(n, 1); /* This special case is taken care of -- one less peak to go */ + + if (n > 0) + { + /* allow for an additional consecutive final plocs after (Fs/2-1) at Fs/2 */ + currPlocs = *pPlocs++; move16(); + } + } + + /* Here the only remaining point would be a fs/2 plocs */ + /* pXfp = xfp + sub(Lprot2,1); already set just a reminder where it whould point */ + IF(n > 0) /* fs/2 which makes special case . */ + { + fraction = imax_fx(pXfp, 1); /* for parabolic this is a special case. */ + + L_acc = L_deposit_h(currPlocs); /* N.B., (*pPlocs) must be 1 here. */ + *pPlocsi_L++ = L_mac(L_acc, fraction, 1); move32(); /* in Q16 */ + currPlocs = *pPlocs++; move16(); + n = sub(n, 1); /* This special case is taken care of -- one less peak to go */ + } + } + + /* here n should be 0 if all peaks have been processed */ + ASSERT(n == 0); + + /* Check number of plocs within an assumed pitch range */ + P_in_plocs = 0; move16(); + FOR(n = 0; n < *num_plocs; n++) + { + /* count number of peaks in locations 1,2,3,4,5,6 , ~= 60 Hz ... 380 Hz */ + fraction = s_min(1, plocs[n]); /* 0 stays zero , otherwise 1 */ + if (sub(plocs[n], 7) < 0) + { + P_in_plocs = add(P_in_plocs, fraction); + } + } + +#ifdef WMOPS + BASOP_sub_sub_end(); /* peaks refine */ +#endif + + logic16(); + IF(f0hzLtpBinQ7 > 0 && P_in_plocs > 0) + { + Word16 n_plocs_in, n_plocs_out; + + n_plocs_in = *num_plocs; move16(); + + /* NB LF peak analysis may add adjacent peaks in { plocs, L_plocsi}, (output from peakfinder did not have + * adjacent peaks ) */ + plc_phEcu_LF_peak_analysis_fx(plocs /* i/o */, num_plocs /* i/o */, L_plocsi /* i/o */, xfp, f0hzLtpBinQ7, + norm_corrQ15_fx, 2, maxPlocs, buffer_fft); + n_plocs_out = *num_plocs; move16(); + + IF(sub(n_plocs_in, n_plocs_out) == 0) + { + /* adjust first peak coinciding with LTPF0 measures if it indicates so */ + plc_phEcu_F0_refine_first_fx(plocs /* i/o */, *num_plocs, L_plocsi /* i/o */, f0hzLtpBinQ7, norm_corrQ15_fx, + 3); + } + } + /* moved inside spec_ana_fx , to include validated pitch peak P_in_plocs*/ + { + Word16 peak_limits_fx[5] = { 14 /*NB*/, 14 /*WB*/, 14 /*sWB*/, 14 /*SWB*/, + 14 /* FB */ }; /* to be trained for each BW */ + + test(); + test(); + IF((sub(norm_corrQ15_fx, 0) > 0) && /* == 0 indicates a negative correlation, which could be likely stable */ + (sub((Word16)(0.5 * 32768), norm_corrQ15_fx) > 0) && (sub(*num_plocs, peak_limits_fx[bwidth_fx]) > 0)) + { + if (P_in_plocs > 0) + { + *num_plocs = 0; move16(); /*activate noise only path only if normcorr vas valid energywise */ + } + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + /*-------------------------------------------------------------------* + * subst_spec_fx() + * + * Substitution spectrum calculation + *-------------------------------------------------------------------*/ + + void subst_spec_fx( + const Word16 *plocs, /* i : The indices of the identified peaks Q0 */ + const Word32 *L_plocsi, /* i : Interpolated positions of the identified peaks Q16 */ + Word16 * num_plocs, /* i/o : Number of identified peaks Q0 */ + const Word16 time_offs, /* i : Time offset Q0 */ + Word16 * X, /* i/o : FFT spectrum */ + const Word16 *mag_chg, /* i : Magnitude modification Q15 */ + const Word16 ph_dith, /* i : Phase dither, 2*PI is not included. (Q15, i.e., between 0.0 and 1.0) */ + const Word16 *is_trans, /* i : (Transient) noise generation flags (either 0 or not 1 ) */ + const Word16 output_frame, /* i : Frame length Q0 */ + Word16 * seed, /* i/o : Random seed */ + const Word16 *alpha, /* i : Magnitude modification factors for fade to average Q15 */ + const Word16 *beta, /* i : Magnitude modification factors for fade to average Q15 */ + const Word16 *Xavg, /* i : Frequency group averages to fade to Q0 */ + const Word16 t_adv /* i : time adjustement excluding time_offs Q0 */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + ,const Word16 fadeout, /* need for DC muting */ + Word16 * nonpure_tone_flag_ptr, /* i/o : non-pure single tone indicator state */ + const Word32 * L_Xavg /* i : Frequency group amp averages for tonal tilt analysis Max upshifted */ +#endif + ) + { + Word16 Xph_short; + Word32 L_corr_phase[MAX_PLOCS], L_Xph; + Word32 *pCorrPhase_L; + Word16 cos_F, sin_F, tmp; + Word16 peak_sin_F = 0, peak_cos_F = 0; + Word16 sin_F_fade2avg, cos_F_fade2avg; + Word16 fs_idx; + Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp; + UWord16 lsb; + Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen; + Word16 pkLocation_1, pkLocation, pkLocation1; + const Word16 *pPlocs; + const Word32 *pPlocsi_L; + Word32 L_acc; + Word16 Lprot_inv; + Word16 k; + Word16 tmp2; + Word16 alpha_local; + Word32 tmp_L; + Word16 mag_chg_local; + const Word16 *gwlpr_fxPlus1; + Word16 one_peak_flag_mask; + Word16 noise_mag_scale_neg; + Word16 up_shift_adj; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("subst_spec_fx", sizeof(struct { + Word16 Xph_short; + Word32 L_corr_phase[MAX_PLOCS], L_Xph; + Word32 *pCorrPhase_L; + Word16 cos_F, sin_F, tmp; + Word16 peak_sin_F, peak_cos_F; + Word16 sin_F_fade2avg, cos_F_fade2avg; + Word16 fs_idx; + Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp; + UWord16 lsb; + Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen; + Word16 pkLocation_1, pkLocation, pkLocation1; + const Word16 *pPlocs; + const Word32 *pPlocsi_L; + Word32 L_acc; + Word16 Lprot_inv; + Word16 k; + Word16 tmp2; + Word16 alpha_local; + Word16 expo; + Word32 tmp_L; + Word16 mag_chg_local; + const Word16 *gwlpr_fxPlus1; + Word16 one_peak_flag_mask; + Word16 noise_mag_scale_neg; + Word16 up_shift_adj; + })); +#endif + + if (time_offs == 0) + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::subst_spec_fx(1st)"); +#endif + } + else + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::subst_spec_fx(N)"); +#endif + } + + + gwlpr_fxPlus1 = &(gwlpr_fx[1]); /* ptr init */ + fs_idx = mult(output_frame, (Word16)(32768.0 / 99.0)); /* truncation needed , i.e no rounding can be applied here */ + ASSERT(fs_idx == (output_frame / 100)); + Lprot = LprotSzPtr[fs_idx];move16(); + Lprot_inv = InvLprot_Q22[fs_idx]; move16(); + + tmp2 = add(mult_r(time_offs, oneOverFrameQ15Tab[fs_idx]), 1);/* save a local burst_len for securing DC and fs/2 muting */ + + /* Correction/evolution phase of the identified peaks */ + IF(s_or(is_trans[0], is_trans[1]) != 0) + { + *num_plocs = 0; move16(); + } + ELSE + { + + tmp = t_adv; + + tmp = add_sat(tmp, time_offs); + /* NB tmp can be stored in Word16 Q0 as max used value is 684+(OFF FRAMELIMIT==60)*480 = 29484 */ + tmp_L = L_mult0(tmp, Lprot_inv); + + + tmp = norm_l(tmp_L); + up_shift_adj = s_max(0, sub(4, tmp)); /* 48kHz : PLC frame 1..49 -> tmp_L<<4 , frame 50..60 -> tmpL<<3 */ + tmp_L = L_shl_sat(tmp_L, sub(4, up_shift_adj)); + tmp = round_fx_sat( tmp_L); + + + pPlocsi_L = L_plocsi; + pCorrPhase_L = L_corr_phase; + FOR(m = 0; m < *num_plocs; m++) + { + + /* tmp has variable resolution 10 or 9 bits */ + ASSERT( up_shift_adj >= 0); + Mpy_32_16_ss(L_shl_pos(*pPlocsi_L++, up_shift_adj), tmp, &L_acc, &lsb); + L_acc = L_add(L_shl_pos(L_acc, 5), lshr(lsb, 11)); + /* 5 lsb's actually unused though, as 6 bits are shifted out */ + *pCorrPhase_L++ = L_acc; move32();/* in Q16. 2*PI is not included. */ + } + } + + one_peak_flag_mask = (Word16)0xFFFF; move16(); /* all ones mask -> keep */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + test(); logic16(); + IF((*num_plocs > 0) && sub(*num_plocs, 3) < 0) + { + one_peak_flag_mask = 0x0000; move16(); /* all zeroes mask -> zeroes in valleys, single clean tone assumed */ + + /* revert initial pure tone decision in some cases */ + logic16(); logic16(); + IF((sub(*nonpure_tone_flag_ptr, 0) < 0) && + ((sub(fs_idx, 2) == 0)/* SemiSWB 24 kHz */ || (sub(fs_idx, 4) >= 0)) /* FB 48 kHz */ + ) + { + /* in the first lost frame analyze spectra and spectral bands to possibly reverse an initial pure sine assumption */ + *nonpure_tone_flag_ptr = plc_phEcu_nonpure_tone_ana_fx(plocs, *num_plocs, X, L_Xavg, Lprot, fs_idx); + +#ifdef LOCAL_PLC2_TON_ANA_DEACTIVATE + *nonpure_tone_flag_ptr = 0; /* dbg of inactive tone analysis */ +#endif + } + + + if (sub(*nonpure_tone_flag_ptr, 0) > 0) + { + /* actually revert single pure tone detection */ /* 0-> mute all surrounding valley bins in evolution , 0xff -> generate noise in all valleys */ + one_peak_flag_mask = (Word16)0xFFFF; move16(); /* all ones mask -> keep */ + } + } +#else + logic16(); + if ((*num_plocs > 0) && sub(*num_plocs, 3) < 0) + { + one_peak_flag_mask = 0x0000; move16(); /* all zeroes mask -> zero */ + } +#endif + + + noise_mag_scale_neg = 0; move16(); /* no change of valley noise magnitude */ + logic16(); + if ((*num_plocs == 0) || (time_offs != 0)) + { /* only adj_scale noise amplitude when we have no WC path , or in all noise frame */ + noise_mag_scale_neg = -32768; move16(); /* all ones --> scale_noise */ + } + + IF(*num_plocs == 0) + { + X[0] = 0; move16(); /* reset DC if there are no peaks */ + X[shr_pos(Lprot, 1)] = 0; move16(); /* also reset fs/2 if there are no peaks */ + } + +#ifdef CR8_A_PLC_FADEOUT_TUNING + /* the binary selection of fadeout scheme */ + tmp = (PLC2_FADEOUT_IN_MS - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES; move16(); + if (fadeout != 0) + { + tmp = (PLC2_FADEOUT_LONG_IN_MS - PLC2_FADEOUT_IN_MS_MIN) / PLC2_FADEOUT_RES; move16(); + } + + IF(sub(tmp2, add(fade_scheme_tab_fx[tmp][1],1) ) > 0) +#else + IF(sub(tmp2, (BURST_ATT_THRESH+1)) > 0) +#endif + { + /* also start DC scaling attenuation */ + X[0] = mult(alpha[0], X[0]); move16(); + /* start fs/by2 attenuation */ + X[shr_pos(Lprot, 1)] = mult(alpha[s_min(add(fs_idx, LGW8K), LGW48K)], X[shr_pos(Lprot, 1)]); move16(); + } + + + lprotBy2Minus1 = sub(shr_pos(Lprot, 1), 1); + + /* for 48k the last (63+1+63) 128/2-1 values above 20 kHz are always zeroes */ + { /* after a last, peak no need to evolve above 20kHz , those coeffs have been/ will be zeroed already */ + /* DC, Xused,ReZeroed, fs/2, ImZeroed, ImUsed */ + /*N: 1, 320 , 63 , 1 , 63 , 320 */ + /*Cind: 0, 1-320, 321-383 , 384 , 385-447, 448 -767 */ + lprotBy2Minus1 = s_min( lprotBy2Minus1, 320); + /*only process up to bin X[320] , 63 coeffs X[321] fwd should already be zeroed */ + } + + i = 1; move16(); /* index in the X[DC, ReX part of X_Sav ,i.e *pReX == X[i] */ + k = 0; move16(); + + pReX = X + i; + im_ind = (Lprot - 1); /* ptr init */ + pImX = X + im_ind; + pPlocs = plocs; + pCorrPhase_L = L_corr_phase; + + + pkLocation_1 = -4; move16(); /* dummy value to avoid Out of Array Read */ + pkLocation = -3; move16(); /* dummy value to avoid Out of Array Read for the *num_plocs==0 case */ + pkLocation1 = -2; move16(); /* dummy value to avoid Out of Array Read */ + + IF (*num_plocs != 0) + { + + pkLocation = *pPlocs; move16(); /* N.B. No post-increment */ + lastPeak = sub(*num_plocs, 1); + if (lastPeak >= 0) + { + pkLocation1 = *pPlocs++; move16(); /* get a next peak */ + } + } + + FOR(m = 0; m < *num_plocs; m++) + { + pkLocation_1 = pkLocation; /* plocs[m - 1] */ move16(); + pkLocation = pkLocation1; /* plocs[m] */move16(); + + /*location dependent update of plocs[m + 1] */ + if ( sub(lastPeak, m) > 0) + { /* only read additional peak when teher is a valid position to read */ + pkLocation1 = *pPlocs++; /* plocs[m + 1] */ move16(); + } + + delta_tmp = shr_pos(sub(sub(pkLocation, pkLocation_1), 1), 1); + if (m == 0) + { + delta_tmp = DELTA_CORR; move16(); /* first peak special case */ + } + delta_corr_dn = s_min(delta_tmp, DELTA_CORR); + + delta_tmp = shr_pos(sub(sub(pkLocation1, pkLocation), 1), 1); + if (sub(m, lastPeak) >= 0) + { + delta_tmp = DELTA_CORR; move16(); + } + delta_corr_up = s_min(delta_tmp, DELTA_CORR); /* last peak special case */ + + + /* Input Xph */ + segmentLen = sub(sub(pkLocation, delta_corr_dn), i); /* may be negative */ + + ASSERT(pReX == &(X[i])); + ASSERT(*pReX == X[i]); /*before first, nth valley*/ + + FOR(j = 0; j < segmentLen; j++) /* valley section , may be skipped for segmentlen < 0 */ + { + + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + + /* phase scrambling */ + rotate_W16_fx(*pReX, *pImX, cos_F, sin_F, &tmp, &im); /* tmp=real part, should be inlined */ + UNUSED(re); + + /* i.e. add a bit of magnitude scrambling around 1.0 in longer bursts */ + *seed = rand_phase_fx(*seed, &sin_F_fade2avg, &cos_F_fade2avg); + IF(noise_mag_scale_neg != 0) + { + valley_magnitude_adj_fx(&tmp, &im, *seed, cos_F); + /* use two random variables */ /*reuse cosF from regular X scrambling, + reuse *seed from fade2avg + */ + } + + IF( beta[k] != 0 ) + { + alpha_local = alpha[k]; /* no move as alpha_local is only needed for debug */ + /* the fade2avg mixing branch, fade2avg and transient downscaling and evolution rotation */ + tmp2 = mult_r(beta[k], Xavg[k]); + + { + tmp2 = s_and(tmp2, one_peak_flag_mask); + tmp = s_and(tmp, one_peak_flag_mask); + im = s_and(im, one_peak_flag_mask); + } + + *pReX++ = mac_r(L_mult(alpha_local, tmp), tmp2, cos_F_fade2avg); move16(); + *pImX-- = mac_r(L_mult(alpha_local, im), tmp2, sin_F_fade2avg); move16(); + } + ELSE + { /* the no fade2avg mixing branch, only transient downscaling and evolution rotation */ + { + tmp = s_and(tmp, one_peak_flag_mask); + im = s_and(im, one_peak_flag_mask); + } + + + *pReX++ = mult_r(mag_chg[k], tmp); move16(); + *pImX-- = mult_r(mag_chg[k], im); move16(); + } + i = add(i, 1); + ASSERT(pReX == &(X[i])); /* nth Valley */ + ASSERT(*pReX == X[i]); /* nth Valley */ + if (sub(i, gwlpr_fxPlus1[k]) >= 0) + { + k = add(k, 1); + } + } /* segment_len 1st++ etc valley excluding last */ + + /* peak area section */ + + e = s_min(lprotBy2Minus1, add(pkLocation, delta_corr_up)); + segmentLen = sub(e, sub(i, 1)); + + + L_Xph = *pCorrPhase_L; move32(); + /* rounding here, add "0.5" before extracting the 10 bits for table lookup */ + Xph_short = s_and(extract_l(L_shr_pos_pos(L_add(L_Xph, (1L << (16 - 10 - 1))), 16 - 10)), 0x3ff); + /* 10 bits precision after radix point, for a virtual 0-1023 sin/cos table lookup */ + + + get_sin_cosQ10opt(Xph_short, &peak_sin_F, &peak_cos_F); + + + ASSERT(pReX == &(X[i])); /*before peak*/ + FOR(j = 0; j < segmentLen; j++) + { + mag_chg_local = mag_chg[k]; /* mag_chg_local actually only need for debugging , no move16()*/ + + UNUSED(ph_dith); + *seed = extract_l(L_mac0(13849, *seed, 31821)); + rotate_W16_fx(*pReX, *pImX, peak_cos_F, peak_sin_F, &tmp, &im); /* should be inlined */ + UNUSED(re); + + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + + IF( beta[k] != 0 ) + { /* fade2avg path alpha*X_sav + beta *Xavg */ + alpha_local = mag_chg_local; /* no move alpha_local only needed for dbg */ + tmp2 = mult_r(beta[k], Xavg[k]); + + + *pReX++ = mac_r(L_mult(alpha_local, tmp), tmp2, cos_F); move16(); + *pImX-- = mac_r(L_mult(alpha_local, im), tmp2, sin_F); move16(); + } + ELSE + { + *pReX++ = mult_r(mag_chg_local, tmp); move16(); + *pImX-- = mult_r(mag_chg_local, im); move16(); + } + + i = add(i, 1); + ASSERT(pReX == &(X[i])); + ASSERT(*pReX == X[i]); + if (sub(i, gwlpr_fxPlus1[k]) > 0) + { + k = add(k, 1); + } + } /* segment_length Peak*/ + pCorrPhase_L++; + } + + segmentLen = sub(lprotBy2Minus1, sub(i, 1)); /* tail/valley noise-bins */ + + /* for 48k the last 63+1+63 = values above 20 kHz */ + { /* after last, peak no need to scramble above 20kHz , those coeffs have been/ will be zeroed already */ + /* DC, Xused,ReZeroed, fs/2, ImZeroed, ImUsed */ + /*N: 1, 320 , 63 , 1 , 63 , 320 */ + /*ind: 0, 1-320, 321-383 ,384 , 385-447, 448 -767 */ + /* segmentLen = sub(320, i-1); */ /*only process up to bin X[320] , 63 coeffs X[321] fwd should already be + zeroed */ + /* ASSERT(i-1+ segmentLen == lprotBy2Minus1 ); */ + } + + ASSERT(*pReX == X[i]); /* before a final valley*/ + FOR(j = 0; j < segmentLen; j++) + { + + + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + rotate_W16_fx(*pReX, *pImX, cos_F, sin_F, &tmp, &im); /* should be inlined , tmp=real part */ + + *seed = rand_phase_fx(*seed, &sin_F_fade2avg, &cos_F_fade2avg); + /* i.e. add a bit of magnitude scrambling around 1.0 in longer bursts */ + IF(noise_mag_scale_neg != 0) + { + valley_magnitude_adj_fx(&tmp, &im, *seed, cos_F); + /*reuse cosF from regular X scrambling, + reuse *seed from fade2avg */ + } + + tmp = s_and(tmp, one_peak_flag_mask); + im = s_and(im, one_peak_flag_mask); + IF(beta[k] != 0) + { /* fade2avg path never in first BFI frame */ + + alpha_local = alpha[k]; /* no move as alpha_local is only needed for debug */ + tmp2 = mult_r(beta[k], Xavg[k]); + { + tmp2 = s_and(tmp2, one_peak_flag_mask); + } + + + *pReX++ = mac_r(L_mult(alpha_local, tmp), tmp2, cos_F_fade2avg); move16(); + *pImX-- = mac_r(L_mult(alpha_local, im), tmp2, sin_F_fade2avg); move16(); + } + ELSE + { + + *pReX++ = mult_r(mag_chg[k], tmp); move16(); + *pImX-- = mult_r(mag_chg[k], im); move16(); + } + i = add(i, 1); + ASSERT(*pReX == X[i]); + if (sub(i, gwlpr_fxPlus1[k]) > 0) + { + k = add(k, 1); + } + } /* segment_len last valley */ + + + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + void my_wtda_fx(const Word16 *new_audio, /* i : input audio to be windowed Q0 20 ms , OPT can be output as well */ + const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + Word32 *L_wtda_audio, /* o : tda audio Q16 20 ms */ + const Word16 L, Word8 *scratchBuffer) /* Size = 8 * MAX_L_FRAME */ + { + Word16 i, L2; /*,L4;*/ + const Word16 *pX; + const Word16 *pW; + Word32 *p1_L, *p2_L, *p3_L, *p4_L; + Word32 *L_w_audio; /*OPt 1 use input buffer , OPT2, may be shortened from 20 ms to 16 ms due to + zeroed parts*/ + Word32 *pY_L, *pa1_L, *pa2_L; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("my_wtda_fx", sizeof(struct { + Word16 i, L2; /*,L4;*/ + const Word16 *pX; + const Word16 *pW; + Word32 *p1_L, *p2_L, *p3_L, *p4_L; + Word32 *L_w_audio; /*OPT 1 use input buffer, OPT2, may be shortened from 20 ms to 16.25+(1.75) ms + due to zeroed parts*/ + Word32 *pY_L, *pa1_L, *pa2_L; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::my_wtda_fx"); +#endif + + L_w_audio = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * 2 * MAX_L_FRAME */ + + /* |111111|222222|333333|444444 */ + /* |p1 p2| p3||p4 */ + + /* Apply analysis window */ + + pX = new_audio; + pY_L = L_w_audio; + + pW = win2ms_init; + FOR(i = 0; i < ((2 * L / 10)); i++) /* Loop over 2ms window MDCT-ana length */ + { + *pY_L++ = L_mult(*pX++, *pW++); move32(); + } + + pW = win16ms_center; + /* 20 ms - 2ms - 3.75 ms = 14.25 ms */ + FOR(i = 0; i < (2 * L - (2 * L / 10) - ((3 * 2 * L) / 16)); + i++) /* Loop over remaining 14.25ms, currently out of a 16 ms stored length */ + { + *pY_L++ = L_mult(*pX++, *pW++); move32(); + } + + + /* tda */ + L2 = shr_pos_pos(L, 1); /* length of tda blocks */ + + p1_L = L_w_audio; /* block 1 fwd */ + p2_L = L_w_audio + L - 1; /* block 2 rev */ + p3_L = L_w_audio + L + L2 - 1; /* block 3 rev */ + p4_L = L_w_audio + L + L2; /* block 4 fwd */ + + pa1_L = L_wtda_audio; /* first part output */ + pa2_L = L_wtda_audio + L2; /* second part output */ + + FOR(i = 0; i < (L / 8); i++) + { + /* first 1.25ms part of tda signal -p3_rev -p4_fwd */ + *pa1_L++ = L_negate(L_add_sat(*p3_L--, *p4_L++)); move32(); + } + FOR(; i < L2; i++) + { + /* first front part 3.75 ms p4_l is zeroes -p3_rev + (-p4_fwd==0) */ + *pa1_L++ = L_negate(*p3_L--); move32(); + } + + FOR(i = 0; i < L2; i++) + { + /* second part of tda signal p1 -p2_rev */ + *pa2_L++ = L_sub_sat(*p1_L++, *p2_L--); move32(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return; + } + + /*-------------------------------------------------------------------------- + * rec_wtda() + * + * Windowing and TDA of reconstructed frame + *--------------------------------------------------------------------------*/ + + + static void + rec_wtda_fx( + Word16 *X, /* i : iFFT(X-evolved) TD-signal o: dbg 16 ms */ + Word32 *L_ecu_rec, /* o : Reconstructed frame in tda domain Qx? */ + const Word16 output_frame, /* i : Frame length */ + const Word16 Lprot, /* i : Prototype frame length */ + const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + const Word16 maxLen, + const Word16 *prevsynth, + const Word16 Q_psMinus1, /*i: Q prev_synth minus 1 , (-1 to match Q of Xsav in first bfi frame ) */ + Word8 *scratchBuffer) /* Size = 12 * MAX_L_FRAME */ + { + Word16 l, Lprot2; + Word16 *rec_buf; + Word16 *xsubst_; /*,*out_ptr;*/ + + Word16 ola_old[COPY_LEN_48K + OLA_LEN_48K]; /* 3.75 ms */ + Word16 work_len; + Word16 copy_len; + Word16 ola_len; + + + Word8 *buffer_wtda; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("rec_wtda_fx", sizeof(struct { + Word16 l, Lprot2; + Word16 *rec_buf; + Word16 *xsubst_; /*,*out_ptr;*/ + Word8 *buffer_wtda; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::rec_wtda_fx"); +#endif + + rec_buf = scratchAlign(scratchBuffer, 0); /* Size = 2 * 2 * MAX_L_FRAME */ + buffer_wtda = (Word8 *)scratchAlign(rec_buf, sizeof(*rec_buf) * (2 * maxLen)); /* Size = 4 * 2 * MAX_L_FRAME */ + + xsubst_ = rec_buf; + Lprot2 = shr_pos_pos(Lprot, 1); + + /* extract reconstructed frame with ld window into rec_buf */ + l = sub(output_frame, Lprot2); + basop_memmove(xsubst_ + l, X, (Lprot) * sizeof(Word16)); /* 16 ms IFFT raw output */ + copy_len = COPY_LEN[FRAME2FS_IDX(output_frame)]; + ola_len = OLA_LEN[FRAME2FS_IDX(output_frame)]; + work_len = add(copy_len, ola_len); + /* Copy and scale copy part 2ms from prevsynth */ + basop_memmove(rec_buf, &prevsynth[Lprot - work_len], (copy_len) * sizeof(Word16)); /* 2ms out of 3.75 ms copied */ + Scale_sig_sat(rec_buf, copy_len, sub(-3, Q_psMinus1)); /* inplace scaling by 2^(-Q_ps-4) */ + + + /* Copy, window and scale 1.75 ms ola part from prevsynth , into a temporary buffer ola_old */ + + + windowing_ola(&prevsynth[Lprot - ola_len], ola_old, w_old[FRAME2FS_IDX(output_frame)], ola_len); /* 1.75 ms */ + + Scale_sig_sat(ola_old, ola_len, sub(-3, Q_psMinus1)); /* inplace scaling by 2^(-Qps-4) */ + + /* Window 1.75 ms length inplace recreated X=IFFT(prototype) signal copied into rec_buf signal */ + windowing_ola(&rec_buf[copy_len], &rec_buf[copy_len], w_new[FRAME2FS_IDX(output_frame)], ola_len); + /* mix add the two windowed components */ + ola_add(&rec_buf[copy_len], ola_old, &rec_buf[copy_len], ola_len); /* OPT: sat check */ + + my_wtda_fx(rec_buf, + win2ms_init, /* i: 2 ms initial part of pre_tda window */ + win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + L_ecu_rec, output_frame, buffer_wtda); /* */ + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + + return; + } + + /*-------------------------------------------------------------------------- + * rec_frame_fx() + * + * Frame reconstruction + *--------------------------------------------------------------------------*/ + void rec_frame_fx(Word16 * x, /* i : FFT spectrum 16 ms, o: ifft() TD debug signal 16ms */ + Word32 * L_ecu_rec, /* o : Reconstructed frame in tda domain 10ms buffer */ + const Word16 output_frame, /* i : Frame length */ + const Word16 Q, /* i : Xsav Q */ + const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + Word16 maxLprot, + const Word16 *prevsynth, + const Word16 Q_prevsynthMinus1, /* i : prevsynthQ-1 or xfp Q */ + Word8 *scratchBuffer /* Size = 4 * MAX_LPROT + 12 * MAX_L_FRAME */ + ) + { + Counter i; + Word16 Lprot; + Word32 *L_x; + Word32 *pX_L; + Word16 *pX; + Word16 fft_scale; + Word8 * buffer_fft; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("rec_frame_fx", sizeof(struct { + Counter i; + Word16 Lprot; + Word32 *L_x; + Word32 *pX_L; + Word16 *pX; + Word16 fft_scale; + Word8 * buffer_fft; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::rec_frame_fx"); +#endif + + L_x = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_LPROT */ + buffer_fft = (Word8 *)scratchAlign(L_x, sizeof(*L_x) * maxLprot); /* Size = 4* (2+1) * MAX_L_FRAME */ + + /* Initialize to FB constants */ + Lprot = mult(output_frame, (Word16)(32768.0 / 99.0)); /* truncation needed , i.e no rounding can be applied here */ + ASSERT(Lprot == (output_frame / 100)); + Lprot = LprotSzPtr[Lprot]; move16(); + + + /* Convert stored 16 bit into 32bit for fft */ + flippedW16_2_intlvW32(x, sub(shr_pos_pos(Lprot, 1), 1), Lprot, L_x); + /*scratch x now free for re-use */ + + fft_scale = -1; move16(); + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::IFFT_fx"); +#endif + BASOP_irfftN(L_x, Lprot, &fft_scale, buffer_fft); +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + + pX_L = &L_x[0]; + pX = &x[0]; /* scratch x reused */ + + { + FOR(i = 0; i < Lprot; i++) + { + *pX++ = extract_h(L_shl_sat(*pX_L++, fft_scale)); move16(); + } + } + /* Scratch L_x may be released */ + + + /* Saturation possible when rescaling to Q0 if there are random bit errors in the bit stream + * One may use one guard bit to better handle this - though it should not be needed for normal + * operation. + */ + Scale_sig_sat(x, Lprot, negate(Q)); /* scale by 2^(-Q) */ + + /*scratch x is Lprot word16 */ + /* scatch need for win-TDA XXX */ + /* scrcatch need for TDA XXX */ + + rec_wtda_fx(x, L_ecu_rec, output_frame, Lprot, + win2ms_init, /* i: 2 ms initial part of pre_tda window */ + win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + s_max(output_frame, 160), + prevsynth, + Q_prevsynthMinus1, /* NB: prevsynth Q may change from prev_bfi=0 to prev_bfi==1, due to phase + of signal or PLC2-muting */ + buffer_fft); + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return; + } + + /*-------------------------------------------------------------------------- + * hq_phase_ecu_fx() + * + * Main routine for HQ phase ECU + *--------------------------------------------------------------------------*/ + void hq_phase_ecu_fx( + const Word16 *prevsynth, /* i : buffer of previously synthesized signal currently 16ms */ + Word32 * L_ecu_rec, /* o : reconstructed frame in tda domain , also tmp w32_fft buffer */ + Word16 * time_offs, /* i/o: Sample offset for consecutive frame losses*/ + Word16 * X_sav, /* i/o: Stored spectrum of prototype frame */ + Word16 * Q_spec, /* o: Q value of stored spectrum */ + Word16 * num_p, /* i/o: Number of identified peaks */ + Word16 * plocs, /* i/o: Peak locations */ + Word32 * L_plocsi, /* i/o: Interpolated peak locations Q16 */ + const Word16 env_stab, /* i : Envelope stability parameter */ + const Word16 f0hzLtpBinQ7, /* i: LTP bin frequency in normalized Hz Q7 */ + const Word16 norm_corrQ15_fx, /*i : correlation for lag at f0hzLtpBinQ7 */ + const Word16 prev_bfi, /* i : indicating burst frame error */ + Word16 old_is_transient[2], /* i/o : flags indicating noise generation frames */ + Word16 * mag_chg_1st, /* i/o: per band magnitude modifier for transients*/ + Word16 * mag_chg_gr, /* o: per band magnitude modifier, incl burst attenuation */ + Word16 * Xavg, /* i/o: Frequency group average gain to fade to */ + Word16 * beta_mute, /* o : Factor for long-term mute */ + const Word16 bwidth_fx, /* i : Encoded bandwidth */ + const Word16 output_frame, /* i : frame length */ + Word16 * seed_out_fxPtr, /* o: utput dbg NULL may be used*/ + Word16 * X_out, /* o: utput dbg NUll may be used */ + const Word16 t_adv, /* i : time adjustment including time_offs */ + const Word16 *const win2ms_init, /* i: 2 ms initial part of pre_tda window */ + const Word16 *const win16ms_center, /* i: 16 ms combined part of pre_tda IWHR+MDCT-ana */ + const Word16 *sp_ana_win, /* i : whr 3+10+3 window */ + Word16 q_fx_old_exp, /* i : exp of prev_synth */ + + Word16 maxLprot, /* i : maz spectrum buffer size */ + Word16 maxPlocs, /* i : max nb of peaks */ + Word32 L_oold_xfp_w_E_fx, Word16 oold_xfp_w_E_exp_fx, /* exp of time signale */ + Word16 oold_Ltot_exp_fx, /*true exp of energy */ + Word16 *oold_grp_shape_fx, Word32 L_old_xfp_w_E_fx, Word16 old_xfp_w_E_exp_fx, /* exp of time signale */ + Word16 old_Ltot_exp_fx, /*true exp of energy */ + Word16 *old_grp_shape_fx, + Word16 margin_prevsynth, +#ifdef CR8_A_PLC_FADEOUT_TUNING + const Word16 fadeout, + Word16 *nonpure_tone_flag_ptr, /* i/o : non-pure single tone indicator state */ +#endif + Word8 *scratchBuffer /* Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */ + ) + { + Word16 lprot; + Word16 *mag_chg, ph_dith, *X; + Word16 *xfp; + Word16 seed; + Word16 alpha[MAX_LGW], beta[MAX_LGW] ; + Word16 prevsynth_man_upshift; + Word16 Q_prevsynthMinus1; + Word8 *buffer; +# ifdef CR8_A_PLC_FADEOUT_TUNING + Word32 L_Xavg[MAX_LGW]; /* i/o : Frequency group amp averages for tonal tilt analysis Max upshifted */ +# endif +#ifdef DYNMEM_COUNT + Dyn_Mem_In("hq_phase_ecu_fx", sizeof(struct { + Counter i; + Word16 lprot; + Word16 *mag_chg, ph_dith, *X; + Word16 seed; + Word16 alpha[MAX_LGW], beta[MAX_LGW]; + Word16 prevsynth_man_upshift; + Word16 Q_prevsynthMinus1; + Word8 *buffer; + // ToDO Word32 L_Xavg[MAX_LGW]; + })); +#endif + + if (!prev_bfi) + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::hq_phase_ecu_fx(1st)"); +#endif + } + else + { +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::hq_phase_ecu_fx(N)"); +#endif + } + + mag_chg = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LGW */ + X = (Word16 *)scratchAlign(mag_chg, sizeof(*mag_chg) * MAX_LGW); /* Size = 2 * MAX_LPROT == 1 Word16*MAX_LPROT */ + xfp = (Word16 *)scratchAlign(X, sizeof(*X) * maxLprot); /* Size = 2 * MAX_LPROT == 1 Word16*MAX_LPROT */ + buffer = (Word8 *)scratchAlign(xfp, sizeof(*xfp) * maxLprot); /* Size = 4 * MAX_LPROT + 12 * MAX_L_FRAME */ + + /* buffer size = Word32 * MAX_LPROT (FFT, IFFT) DRAM + + 3*Word32 * MAX_L_FRAME */ + + basop_memset(alpha, 0, MAX_LGW*sizeof(Word16)); + basop_memset(beta, 0, MAX_LGW*sizeof(Word16)); + + lprot = LprotSzPtr[bwidth_fx]; move16(); + + test(); + ASSERT(prev_bfi >= 0 && prev_bfi <= 1); + IF( prev_bfi == 0 ) /* inside PhECU we can check vs 0 */ + { + *time_offs = 0; move16(); +#ifdef CR8_A_PLC_FADEOUT_TUNING + *nonpure_tone_flag_ptr = -1; move16(); /* flag nonpure tone flag for new analysis */ +#endif + /* analysis made outside, up/down scaling here from static RAM to dynamic RAM */ + /* prevsynth_in_flt = prev_synth_man*2.^(-15 + exp_old) */ + /* X_sav_flt = X_man/2.^(Q_spec) */ + + /* 1 bit headroom needed in xfp_tmp_buf for FFT processing into X_sav */ + /* margin_prevsynth = actual margin in incoming 16 ms xpf segment */ + /* q_fx_old_exp was computed on full 21+ ms updatepcm buffer) */ + + ASSERT(margin_prevsynth >= 0 && (margin_prevsynth <= 16)); + + prevsynth_man_upshift = + sub(margin_prevsynth, 1); /* 0 --> -1(==down), 1--> 0 , 2 --> 1(==up), ... */ + ASSERT(prevsynth_man_upshift >= -16 && prevsynth_man_upshift <= 15); /* avoid Overflow in shr, shl */ + *Q_spec = sub(15, sub(q_fx_old_exp, prevsynth_man_upshift)); + /* Q_spec target is to create 1 additional bit of margin in the xfp TD buffer , before converting to + * Xsav + */ + + if (margin_prevsynth == 0) + { + Word16 Qold = 15 - (q_fx_old_exp + 1); + Word16 tmp_man_upshift = margin_prevsynth - 1; /* 1 .. -15 */ + Word16 Qnew = 15 - (q_fx_old_exp - tmp_man_upshift); + assert(Qold == Qnew); + UNUSED(Qold); + UNUSED(Qnew); + } + if (margin_prevsynth == 1) + { + Word16 Qold = 15 - (q_fx_old_exp + 0); + assert(*Q_spec == Qold); + UNUSED(Qold); + } + if (margin_prevsynth == 2) + { + Word16 Qold = 15 - (q_fx_old_exp - 1); + assert(*Q_spec == Qold); + UNUSED(Qold); + } + + Q_prevsynthMinus1 = sub(15, add(q_fx_old_exp, +1)); /* dbg to use non-scaled prevsynth for OLA */ + + /* Q of prev_synth now separated from prev_bfi=0 and prev_bfi==1 */ + +#ifdef USE_TMPXFP_IN_OLA + Q_prevsynthMinus1 = *Q_spec; /* a possibly upscaled Q */ +#endif + + + Copy_Scale_sig( + prevsynth, xfp, lprot, + prevsynth_man_upshift); /* unscaled prevsynth is still used by rec_frame, copy to a temporary + xfp analysis buffer, and scale down to a margin of 1 bit */ + + + trans_burst_ana_fx( + ((void *)NULL), + mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab, alpha, beta, beta_mute, Xavg, + (*Q_spec), L_oold_xfp_w_E_fx, oold_xfp_w_E_exp_fx, oold_Ltot_exp_fx, oold_grp_shape_fx, + L_old_xfp_w_E_fx, old_xfp_w_E_exp_fx, old_Ltot_exp_fx, old_grp_shape_fx, +#ifdef CR8_A_PLC_FADEOUT_TUNING + fadeout, + L_Xavg, /* full scale band amplitudes in first bfi frame */ +#endif + buffer); + + spec_ana_fx(&(xfp[0]), plocs, L_plocsi, num_p, X_sav, output_frame, bwidth_fx, + sp_ana_win, f0hzLtpBinQ7, norm_corrQ15_fx, maxLprot, maxPlocs, buffer); + } + ELSE + { + /* analysis made outside, possible up/down scaling here from static RAM to dynamic RAM */ + ASSERT(margin_prevsynth >= 0 && (margin_prevsynth <= 15)); + + /* prev_synth may have been scaled outside by update_pcm() function */ + /* prevsynth_in_flt = prev_synth_man*2.^(-15 + exp_old) */ + /* first bfi frame: X_sav_flt = X_man/2.^(*Q_spec) */ + /* this bfi frame prev_synth(TD) is mixed with ifft signal(TD,from Q_spec) in rec_frame_fx + variable Q_prevsynthMinus1 provided to rec_frame for this TD+TD mixing + */ + + Q_prevsynthMinus1 = sub(15, add(q_fx_old_exp, +1)); /* for now, "old" use of unscaled prevsynth for added OLA */ + +#ifdef USE_TMPXFP_IN_OLA + { /* DBG target here is to instead upshift to a zero margin */ + /* but Q value is maintained to match the save Xsav *Q_spec which is used with an offset of " -1" */ + /* prevsynth_man_upshift = -prevsynth_margin ; */ + Word16 tmp, worklen = add(hamm_len2Tab[bwidth_fx], shr(hamm_len2Tab[bwidth_fx], 2)); + tmp = mult(7680, lprot); /* needs to truncate to integer */ + ASSERT(tmp == worklen); + Copy_Scale_sig(&prevsynth[lprot - worklen], &xfp[lprot - worklen], worklen, + margin_prevsynth); /* only scale up last 3.75 ms */ + Q_prevsynthMinus1 = sub(15, add(q_fx_old_exp, margin_prevsynth)); /*-1 does not make sense */ + } +#endif + + *time_offs = add_sat(*time_offs, output_frame); + + trans_burst_ana_fx( + ((void *)NULL), + mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab, alpha, beta, beta_mute, Xavg, + (0), /* *Q_spec input only used in first bfi frames for burst analysis */ + L_oold_xfp_w_E_fx, oold_xfp_w_E_exp_fx, oold_Ltot_exp_fx, oold_grp_shape_fx, L_old_xfp_w_E_fx, + old_xfp_w_E_exp_fx, old_Ltot_exp_fx, old_grp_shape_fx, +#ifdef CR8_A_PLC_FADEOUT_TUNING + fadeout, + NULL, /* full scale band amplitudes , only used in first bfi frame */ +#endif + buffer); + } + /* cpy LPROT Word16 from Static RAM Xsav to working DRAM/scratch buffer X ;*/ + basop_memmove(X, X_sav, (lprot) * sizeof(Word16)); + /* seed for own_rand2 */ + seed = *time_offs; move16(); + + if (mag_chg_gr != NULL) /* o: dbg per band magnitude modifier, incl. burst attenuation */ + { + Counter k; + Word16 lgw_local = s_min(add(bwidth_fx, LGW8K), LGW48K); /* 4,5,6,7, (7/8) */ + for (k = 0; k < lgw_local; k++) + { + mag_chg_gr[k] = mag_chg[k]; /* dbg SNR output */ + } + } + + subst_spec_fx(plocs, L_plocsi, num_p, *time_offs, X, mag_chg, ph_dith, old_is_transient, output_frame, + &seed, alpha, beta, + Xavg, t_adv +#ifdef CR8_A_PLC_FADEOUT_TUNING + ,fadeout, + nonpure_tone_flag_ptr, /* i/o : non-pure single tone indicator state */ + L_Xavg /*i : only used in first bfi frame */ +#endif + ); + + if (seed_out_fxPtr != NULL) + { + *seed_out_fxPtr = seed; /* verify seed synch after subst_spec */ + } + + + if (X_out != NULL) + { + Word16 ii; + for (ii = 0; ii < lprot; ii++) + { + X_out[ii] = X[ii]; /* evolve spectrum, no moves counted as this is a dbg-vector info cpy */ + } + } + + /* reconstructed frame in tda domain */ + /* NB *Q_spec only updated in first bfi frame */ + + /*Scratch Analysis at this point */ + /* X fft input needed as evolved spectrum Lprot* Word16 */ + /* xfp not needed any longer Word16* Lprot */ + /* IFFT operation needs Word32*Lprot in and Word32*Lprot out */ + /* MDCT win operation may be inplace 2x MAX_L_FRAME */ + /* TDA output is 1x MAX_L_FRAME */ + + rec_frame_fx(X, L_ecu_rec, output_frame, *Q_spec, + win2ms_init, win16ms_center, + maxLprot, +#ifdef USE_TMPXFP_IN_OLA + xfp, /* only last 3.75 ms used, in both prevbfi=0 and prevBfi=1 i.e frames, xfp is an + upscaled prev_synth */ +#else + prevsynth, /*only last 3.75 ms used in both prevbfi=0 and prevBfi=1 i.e frames */ +#endif + Q_prevsynthMinus1, + buffer); + + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + + static Word16 sqrt2ndOrder( /* o: in Q15 (2nd order least square approx.) */ + const Word16 x /* i: x must be in between 0.5 and 1.0 (Q15). */ + ) + { + Word32 acc; + Word16 z; +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::sqrt2ndOrder"); +#endif + + ASSERT(x >= 16384); + + acc = 1890205600L; /* 0.880195572812922 in Q31 */ move32(); + z = mac_r(acc, x, -6506); /* -0.198537395405340 in Q15 */ + acc = 682030261L; /* 0.317595089462249 in Q31 */ move32(); + z = mac_r(acc, z, x); /* in Q15 */ + + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return z; + } + + + /* Modified version to produce Word32 input to FFT */ + static void windowing_L( + const Word16 *x, /* i: Input signal */ + Word32 * L_y, /* o: Windowed output */ + const Word16 *win, /* i: Window coefficients */ + const Word16 rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */ + const Word16 halfLength /* i: Half of the total length of a complete Hamming window. */ + ) + { + Counter i; + Word32 * pY_L; + const Word16 *pX, *pW; + Word16 tmp_RL; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("windowing_L", sizeof(struct { + Counter i; + Word32 * pY_L; + const Word16 *pX, *pW; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::windowing_L"); +#endif + + pX = x; + pW = win; + pY_L = L_y; + + FOR(i = 0; i < halfLength; i++) /* 1st symmetric half of the Hamming window */ + { + *pY_L++ = L_mult(*pX++, *pW++); move32(); + } + /* Periodic filter - one more rect sample before end tapering */ + + tmp_RL = add(rectLength, 1); + + if (rectLength == 0) + { + tmp_RL = 0; move16(); + } + /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */ + FOR(i = 0; i < tmp_RL;i++) + { + *pY_L++ = L_deposit_h(*pX++); move32(); + } + tmp_RL = sub(halfLength, 1); + if (rectLength == 0) + { + tmp_RL = halfLength; move16(); + } + FOR(i = 0; i < tmp_RL; i++) /* 2nd symmetric half of the Hamming window. */ + { + *pY_L++ = L_mult(*pX++, *(--pW)); move32(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + /* Modified version to produce Word16 input to FFT */ + static void windowing_ola(const Word16 *x, /* i: Input signal */ + Word16 * y, /* o: Windowed output */ + const Word16 *win, /* i: Window coefficients */ + const Word16 Length /* i: Half of the total length of a complete Hamming window. */ + ) + { + Counter i; + Word16 * pY; + const Word16 *pX, *pW; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("windowing_ola", sizeof(struct { + Counter i; + Word16 * pY; + const Word16 *pX, *pW; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::windowing_ola"); +#endif + + pX = x; + pW = win; + pY = y; + + FOR(i = 0; i < Length; i++) /* 1st symmetric half of the Hamming window */ + { + *pY++ = mult_r(*pX++, *pW++); move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + /* Modified version to produce Word16 input to FFT */ + static void ola_add(const Word16 *x, /* i: Input signal 1 */ + const Word16 *y, /* i: Input signal 2 */ + Word16 * z, /* o: Output signal */ + const Word16 Length /* i: Half of the total length of a complete window. */ + ) + { + Counter i; + Word16 * pZ; + const Word16 *pX, *pY; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("windowing_ola", sizeof(struct { + Counter i; + Word16 * pY; + const Word16 *pX, *pW; + })); +#endif + + + + pX = x; + pY = y; + pZ = z; + + FOR(i = 0; i < Length; i++) /* 1st symmetric half of the Hamming window */ + { + *pZ++ = add_sat(*pX++, *pY++); move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + + } + + /*----------------------------------------------------------------------------- + * magnSqrtApprox_fx() + * + * Approximation of sqrt(Square magnitude) of fft spectrum + * if min_abs <= 0.4142135*max_abs + * abs = 0.99*max_abs + 0.197*min_abs + * else + * abs = 0.84*max_abs + 0.561*min_abs + * end + * + * Note: even to handle the dynamics of sqrt(re^2+im^2) located on + * a scaled unit circle. One need to scale down the results + * with a factor 2, that is Q_out = Q_in - 1 + * sqrt(32768.^2+32768.^2) results in = 23170 Q0-1, + * which corresponds to 46341 in the Q0 domain + *----------------------------------------------------------------------------*/ + Word16 sqrtMagnApprox_fx( /* o : sqrt of magnitude square spectrum Q_in-1*/ + const Word16 re, /* i : Real part Q_in */ + const Word16 im /* i : Imag part Q_in */ + ) + { + /* Constants for Approximation of sqrt(Square magnitude) of fft spectrum + * >> num2str(round(0.4142135]*2.^15)) + * ans = 13573 + * >> num2str(round([0.99 0.197 0.84 0.561]*2.^14)) + * ans = 16220 3228 13763 9191 + */ + +#define C_0p4142135_Q15 13573 + +#define C_0p99_Q14 16220 +#define C_0p197_Q14 3228 +#define C_0p84_Q14 13763 +#define C_0p561_Q14 9191 + Word16 sgn_bit, re_abs, im_abs, max_abs, min_abs, sum; + Word16 jcoeffs[2][2] = { {C_0p99_Q14, C_0p197_Q14}, {C_0p84_Q14, C_0p561_Q14} }; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("sqrtMagnApprox_fx", sizeof(struct { + Word16 sgn_bit, re_abs, im_abs, max_abs, min_abs, sum; + Word16 jcoeffs[2][2]; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::sqrtMagnApprox_fx"); +#endif + + /* Get values and move pointers */ + re_abs = abs_s(re); /* 1 cycle */ + im_abs = abs_s(im); /* 1 cycle */ + + /* Find max and min value */ + min_abs = s_min(re_abs, im_abs); /* 1 cycle */ + max_abs = s_max(re_abs, im_abs); /* 1 cycle */ + + /* Calc approximation depending on relation */ + sgn_bit = lshr(sub(mult(max_abs, C_0p4142135_Q15), min_abs), 15); /* 3 cycles */ + sum = mac_r(L_mult(max_abs, jcoeffs[sgn_bit][0]), min_abs, jcoeffs[sgn_bit][1]); /* 2 cycles */ +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return sum; + } + + /*----------------------------------------------------------------------------- + * fft_spec2_sqrt_approx_fx() + * + * Approximation of sqrt(Square magnitude) of fft spectrum + * if min_abs <= 0.4142135*max_abs + * abs = 0.99 max_abs + 0.197*min_abs + * else + * abs = 0.84 max_abs + 0.561*min_abs + * end + * + * Note: even to handle the dynamics of sqrt(re^2+im^2) located on + * a scaled unit circle. One need to scale down the results + * with a factor 2, that is Q_out = Q_in - 1 + * sqrt( -32768.^2 + -32768.^2 ) results in = 23170 Qin-1, + * which corresponds to 46341 in the Qin domain + *----------------------------------------------------------------------------*/ + + void fft_spec2_sqrt_approx_fx(const Word16 x[], /* i : Input vector: complex spectrum , Qin */ + Word16 xMagSqrt[], /* o : sqrt of magnitude square spectrum Qout=Qin-1*/ + const Word16 N /* i : Input vector x length */ + ) + { + Counter i; + Word16 l; + const Word16 *pRe, *pIm; + Word16 * pMagSqrt; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("fft_spec2_sqrt_approx_fx", sizeof(struct { + Counter i; + Word16 l; + const Word16 *pRe, *pIm; + Word16 * pMagSqrt; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::fft_spec2_sqrt_approx_fx"); +#endif + + /* Magnitude at 0. only real component */ + pMagSqrt = &xMagSqrt[0]; + pRe = &x[0]; + *pMagSqrt++ = mult(abs_s(*pRe++), C_0p99_Q14); move16(); + + /* From 1 to (N/2 - 1). */ + pIm = &x[N - 1]; + + l = sub(shr_pos_pos(N, 1), 1); /* N/2 - 1. */ + l = s_min(l, (LPROT48K_RED / 2 - 1) + DELTA_CORR_F0_INT); + /* at 48 k the top 8 khz are always zero, and further peaks are not + located above LPROT48K_RED 32 kHz */ + FOR(i = 0; i < l; i++) + { + *pMagSqrt++ = sqrtMagnApprox_fx(*pRe++, *pIm--); move16(); + } + + /* The sqrt magnitude square at N/2 - only real component */ + *pMagSqrt = mult(abs_s(*pRe), C_0p99_Q14); move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return; + } + + Word16 + imax2_jacobsen_mag_fx(/* o: The location, relative to the middle of the 3 given data point, of the maximum. + (Q15) */ + const Word16 *y_re, /* i: The 3 given data points. real part order -1 0 1 */ + const Word16 *y_im, /* i: The 3 given data points. imag part order 1 0 -1 (from FFT)*/ + const Word16 + special /* i: -1 = left edge special case, 0 = normal, +1 = right edge special case */ + ) + { + Word16 posi; + Word16 man, expo; + const Word16 *pY; + Word16 y_m1_re, y_0_re, y_p1_re; + Word16 y_m1_im, y_0_im, y_p1_im; + + Word16 D_re, D_im, N_re, N_im; + + Word32 L_sign, L_denom, L_numer; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("imax2_jacobsen_mag_fx", sizeof(struct { + Word16 posi; + Word16 man, expo; + const Word16 *pY; + Word16 y_m1_re, y_0_re, y_p1_re; + Word16 y_m1_im, y_0_im, y_p1_im; + Word16 D_re, D_im, N_re, N_im; + Word32 L_sign, L_denom, L_numer; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::imax2_jacobsen_mag_fx"); +#endif + + /* Jacobsen estimates peak offset relative y_0 using + * X_m1 - X_p1 + * d = REAL ( ------------------- ) * c_jacob + * 2*X_0 - X_m1 -Xp1 + * + * Where c_jacob is a window dependent constant + */ +#define C_JACOB_Q14 18725 /* c_jacob = 1.1429; % assume 0.1875 hammrect window 'periodic' */ + + ASSERT(special == 0); /* always use other imax for edges cases */ + UNUSED(special); + + /* Get the bin parameters into variables */ + pY = y_re; + y_m1_re = *pY++; + y_0_re = *pY++; + y_p1_re = *pY++; + + /* Same for imaginary parts - note reverse order from FFT */ + pY = y_im; + y_p1_im = *pY++; + y_0_im = *pY++; + y_m1_im = *pY++; + + test(); + IF( norm_s(y_0_re) == 0 || norm_s(y_0_im) == 0 ) + { +#define JACOB_MARGIN 2 + /* for very high peaks the Complex denominator values may need to be downshifted 2 steps */ + y_0_re = shr_pos(y_0_re, JACOB_MARGIN); + y_0_im = shr_pos(y_0_im, JACOB_MARGIN); + + y_m1_re = shr_pos(y_m1_re, JACOB_MARGIN); + y_m1_im = shr_pos(y_m1_im, JACOB_MARGIN); + + y_p1_re = shr_pos(y_p1_re, JACOB_MARGIN); + y_p1_im = shr_pos(y_p1_im, JACOB_MARGIN); + } + + /* prepare numerator real and imaginary parts*/ + N_re = sub(y_m1_re, y_p1_re); + N_im = sub(y_m1_im, y_p1_im); + + /* prepare denominator real and imaginary parts */ + + D_re = sub(sub(shl_pos(y_0_re, 1), y_m1_re), y_p1_re); + D_im = sub(sub(shl_pos(y_0_im, 1), y_m1_im), y_p1_im); + + /* REAL part of complex division */ + L_numer = L_mac0(L_mult0(N_re, D_re), N_im, D_im); + L_denom = L_mac0(L_mult0(D_re, D_re), D_im, D_im); + L_sign = L_xor(L_numer, L_denom); /* Preserve the sign since div_s() only takes positive arguments. */ + + L_numer = L_abs(L_numer); + L_denom = L_abs(L_denom); + + test(); + IF(L_numer != 0 && L_denom != 0) + { + + man = plc_phEcu_ratio_fx(L_numer, L_denom, &expo); /* The mantissa is considered in Q15 */ + + man = mult_r(man, C_JACOB_Q14); + posi = shr_sat( man, sub(expo, 2)); + /* to Q15 (and due to saturation, it is automatically bound inside [-1.0,1.0].) */ + + if (L_sign < 0) /* Restore the sign. */ + { + posi = negate(posi); + } + } + ELSE + { + posi = 0; move16(); /* flat top, division is not possible choose center freq */ + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return posi; /* Q15. The position either left or right relative to the index of the middle of the 3 given + data points. */ + } + + /* Convert 32 Bit FFT into 16 bit fft domain */ + static void intlvW32_2_flippedW16( + Word32 * L_x, /* i : interleaved coeffs DC, Fs/2, Re(1),Im(1), Re(2),Im(2), ... ] */ + const Word16 numPairs, /* i: typically (fft-size/2 -1), re/im coeffs to copy */ + const Word16 Lprot, /* i: fft size , including DC+fs/2 */ + Word16 * x /* o : flipped coeffs , [DC, Re(1),.. Re(N-1/2) , Fs/2, Im(N-1/2) ... Im(1) ] */ + ) + { + + /* reorder real and imag components, and apply fractional scale for 24/48Khz */ + Counter m; + Counter numPairsLocal; + Word32 *pX_L = &L_x[2]; /*ptr init*/ + Word16 *pX_Re = &x[1]; /*ptr init*/ + Word16 *pX_Im = &x[Lprot - 1]; /*ptr init*/ + +#define FHG_FFT_UPSHIFT 2 + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::intlvW32_2_flippedW16"); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_In("intlvW32_2_flippedW16", sizeof(struct { + Counter m; + Counter numPairsLocal; + Word32 *pX_L; + Word16 *pX_Re; + Word16 *pX_Im; + })); +#endif + + /* make the scaling of 8/3= 4*0.666 here for 24 kHz and 48 kHz using 16x16 instead or 32x16 ops + a limited loss of SNR */ + + test(); + IF(sub(numPairs, 383) == 0 || sub(numPairs, 191) == 0) + { /* 24,48 kHz , 16 ms , scale by 8/3 = .666*4 */ + numPairsLocal = s_min(numPairs, 383 - 63); /* do not copy bins above 20 kHz */ + /* for 48 kHz is to only go up to 40 kHz pairs , */ + FOR(m = 0; m < numPairsLocal; m++) + { + /* multiply by (8/3)*(2.^FHG_FFT_UPSHIFT) */ + /* note: multiplication by 2/3 need to preceed upshift , due to FFT scaling being very close to the 48/24 3 + * split kHz bit margin */ + *pX_Re++ = extract_h(L_shl_pos(Mpy_32_16_lc3plus(*pX_L++, FEC_TWOTHIRDS_Q15), FHG_FFT_UPSHIFT + 2)); + move16(); + *pX_Im-- = extract_h(L_shl_pos(Mpy_32_16_lc3plus(*pX_L++, FEC_TWOTHIRDS_Q15), FHG_FFT_UPSHIFT + 2)); + move16(); + } + /* Place the two real only components */ + x[0] = extract_h(L_shl_pos(Mpy_32_16_lc3plus(L_x[0], FEC_TWOTHIRDS_Q15), FHG_FFT_UPSHIFT + 2)); /* DC */ + move16(); + m = shr_pos_pos(Lprot, 1); + x[m] = extract_h(L_shl_pos(Mpy_32_16_lc3plus(L_x[1], FEC_TWOTHIRDS_Q15), FHG_FFT_UPSHIFT + 2)); /* fs/2 */ + move16(); + } + ELSE + { /* 8,16,32 kHz 16 ms no additional scaling by 8/3 */ + + FOR(m = 0; m < numPairs; m++) + { + *pX_Re++ = extract_h(L_shl_pos(*pX_L++, FHG_FFT_UPSHIFT)); + move16(); + *pX_Im-- = extract_h(L_shl_pos(*pX_L++, FHG_FFT_UPSHIFT)); + move16(); + } + + /* Place the two real only components */ + x[0] = extract_h(L_shl_pos(L_x[0], FHG_FFT_UPSHIFT)); /* DC */ move16(); + m = shr_pos_pos(Lprot, 1); + x[m] = extract_h(L_shl_pos(L_x[1], FHG_FFT_UPSHIFT)); /* fs/2 */ move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + static void flippedW16_2_intlvW32( + Word16 * x, /* i : flipped coeffs , [DC, Re(1),.. Re(N-1/2) , Fs/2, Im(N-1/2) ... Im(1) ] */ + const Word16 numPairs, /* i: typically (fft-size/2 -1), re/im coeffs to copy */ + const Word16 Lprot, /* i: fft size , including DC+fs/2 */ + Word32 * L_x /* o : interleaved coeffs DC, Fs/2, Re(1),Im(1), Re(2),Im(2), ... ] */ + ) + { + Counter i; + Counter numPairsLocal; + Word32 *pX_L; + Word16 *pX_re, *pX_im; +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::flippedW16_2_intlvW32"); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_In("flippedW16_2_intlvW32", sizeof(struct { + Counter i; + Counter numPairsLocal; + Word32 *pX_L; + Word16 *pX_re, *pX_im; + })); +#endif + + /* Convert stored 16 bit into 32bit for fft */ + /* Note during save FFT output was left shifted FHG_FFT_UPSHIFT */ + /* this needs to be restored before one calls ifft to avoid overflow */ + + pX_L = &L_x[2]; /*ptr init*/ + pX_re = &x[1]; /*ptr init*/ + pX_im = &x[Lprot - 1]; /*ptr init*/ + + numPairsLocal = s_min(320, numPairs); /* 48kHz optimization */ + FOR(i = 0; i < numPairsLocal; i++) + { + *pX_L++ = L_shr_pos(L_deposit_h(*pX_re++), FHG_FFT_UPSHIFT); move32(); + *pX_L++ = L_shr_pos(L_deposit_h(*pX_im--), FHG_FFT_UPSHIFT); move32(); + } + /* at 48KHz zero tail 2x63= 126 bins for Word32 IFFT input */ + basop_memset(pX_L, 0, sizeof(Word32) * shl_pos(sub(numPairs, numPairsLocal), 1)); + + /* Place the two real only components */ + L_x[0] = L_shr_pos(L_deposit_h(x[0]), FHG_FFT_UPSHIFT); move32(); + L_x[1] = L_shr_pos(L_deposit_h(x[Lprot / 2]), FHG_FFT_UPSHIFT); move32(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + + void get_sin_cosQ10opt(Word16 phase, /* Q10 0..1023 i.e. 1024=2*pi */ + Word16 * ptrSin, /* Q15 */ + Word16 * ptrCos /* Q15 */ + ) + { + Word16 sign_val, idx, idx2, idx3; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("get_sin_cosQ10", sizeof(struct { Word16 sign_val, idx, idx2, idx3; })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::get_sin_cosQ10opt"); +#endif + + /* sin table has a range up to pi/2 (256+1)=257 coeffs*/ + + sign_val = shr_pos_pos(phase, 9); /* highest bit is the sinus sign */ + idx = s_and(phase, 0x1ff); /* mask away sign */ + + idx2 = sub(idx, 256); + if (idx2 < 0) + { /*rising sine part */ + *ptrSin = sin_quarterQ15_fx[idx]; move16(); + } + + idx3 = sub(512, idx); + if (idx2 >= 0) + { /* decaying part, reverse idx */ + *ptrSin = sin_quarterQ15_fx[idx3]; move16(); + } + + if (sign_val != 0) + { + *ptrSin = negate(*ptrSin); /*no move when inlined , no sat as max in table is 32767 */ + } + + /*cos*/ + idx = add(phase, 256); /* +pi/2, i.e. move to cos phase */ + idx = s_and(idx, 0x3ff); /* wrap on 10 bits limit */ + + sign_val = shr_pos_pos(idx, 9); /* highest bit is the sign */ + idx = s_and(idx, 0x1ff); /* mask away sign */ + + idx2 = sub(idx, 256); + if (idx2 < 0) + { /*rising sine part */ + *ptrCos = sin_quarterQ15_fx[idx]; move16(); + } + + idx3 = sub(512, idx); + if (idx2 >= 0) + { /* decaying part, reverse idx*/ + *ptrCos = sin_quarterQ15_fx[idx3]; move16(); + } + + if (sign_val != 0) + { + *ptrCos = negate(*ptrCos); /* no move when inlined , no sat as max in table is 32767 */ + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + } + +#ifdef CR8_A_PLC_FADEOUT_TUNING + static Word16 plc_phEcu_nonpure_tone_ana_fx(const Word16* plocs, + const Word16 n_plocs, + const Word16* X, /*i: { DC, Re1,Re2 ,.....ReN , Fs/2, ImN... , Im2, Im1} */ + const Word32 *L_Xavg, /* i : Frequency group amp averages for tonal tilt analysis Max upshifted */ + const Word16 Lprot, + const Word16 fs_idx) + { +#ifdef DYNMEM_COUNT + Dyn_Mem_In("PhECU::nonpure_tone_ana", sizeof(struct { + Word16 nonpure_tone_detect; + Word16 n_ind, tone_ind, low_ind, high_ind; + Word16 peak_amp, peak_amp2, valley_amp, x_abs[(1 + 2 * ONE_SIDED_SINE_WIDTH + 2 * 1)]; + Word16 sineband_ind_low, sineband_ind_high; + Word16 i, N_grp; + Word16 tmp, tmp_dB; + Word32 L_tot_inc_HF, L_tot_inc_LF; + Word16* pRe; + Word16* pIm; + Word16* gwlpr_fxPlus1; + Word32 L_nf; + Word32 L_XavgL2_fx[MAX_LGW + 1]; + Word32 L_XavgUp_fx[MAX_LGW + 1]; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhEcu::nonpure_tone_ana_fx"); +#endif + + Word16 nonpure_tone_detect; /* output variable */ + Word16 n_ind, tone_ind, low_ind, high_ind; + Word16 peak_amp, peak_amp2, valley_amp, x_abs[(1 + 2 * ONE_SIDED_SINE_WIDTH + 2 * 1)]; + + Word16 sineband_ind_low, sineband_ind_high; + Word16 i, N_grp; + Word16 tmp; + + Word32 L_Ltot_inc_HF, L_Ltot_inc_LF; + Word32 L_tmp_dB; + + const Word16* pRe; + const Word16* pIm; + const Word16* gwlpr_fxPlus1; + Word32 L_nf; + Word32 L_XavgL2_fx[MAX_LGW + 1], L_tmp ; + Word32 L_XavgUp_fx[MAX_LGW + 1]; /* upscaled values , excluding peak band(s) */ + + /* use of a compressed hearing sensitivity curve allowing more energy deviation in highest and lowest bands */ + /* ROM table Word16 scATHFx[MAX_LGW - 1] */ + + /* init */ + nonpure_tone_detect = 0; move16(); /* Word16 register with decisions */ + + peak_amp = 0; move16(); + peak_amp2 = 0; move16(); + + /* limit single sine optimization to when 2 peaks are close enough to represent a single sinusoid */ + test(); + if ((sub(n_plocs, 2) == 0) && + (sub(sub(plocs[1], plocs[0]), ONE_SIDED_SINE_WIDTH) >= 0) + ) /* NB, plocs is an ordered vector */ + { + nonpure_tone_detect = s_or(nonpure_tone_detect, 0x01); + } + + /* local bin wise dynamics analysis, for 1 or 2 initial local maxima peaks , + if 2 peaks , we do the analysis based on the location of the largest abs peak */ + { + tone_ind = 0; move16(); /* one peak only , use position plocs[tone_ind], tone_ind==0 */ + + peak_amp = shr(abs_s(X[0]), 1); /* plocs[0]=0, simply multiply DC*0.5 to match scaling in function sqrtMagnApprox_fx */ + test(); + IF(plocs[0] != 0) + { + peak_amp = sqrtMagnApprox_fx(X[plocs[0]], X[sub(Lprot, plocs[0])]); + } + + IF(sub(n_plocs, 2) == 0) /* locate abs max peak */ + { + peak_amp2 = sqrtMagnApprox_fx(X[plocs[1]], X[sub(Lprot, plocs[1])]); /* Re-part and Im-part in different ends of array X */ + + tmp = sub(peak_amp, peak_amp2); + tone_ind = lshr(tmp, 15); /* mask out sign bit 0(for peak_amp0), 1( for peak_amp2), lshr --> no sign extension in shift */ + peak_amp = s_max(peak_amp, peak_amp2); + } + + low_ind = s_max(1, sub(plocs[tone_ind], (ONE_SIDED_SINE_WIDTH + 1))); /* DC is not allowed in the range */ + high_ind = s_min(sub(shr(Lprot, 1), 2), add(plocs[tone_ind], (ONE_SIDED_SINE_WIDTH + 1))); /* Fs/2 is not allowed in the range */ + + n_ind = add(sub(high_ind, low_ind), 1); + /* find lowest amplitude around the assumed main lobe center location */ + + pRe = &(X[low_ind]); /* ptr init */ + pIm = &(X[Lprot - low_ind]); /* ptr init*/ + FOR(i = 0; i < n_ind; i++) + { + x_abs[i] = sqrtMagnApprox_fx(*pRe++, *pIm--); move16(); /* x_abs is downscaled by 0.5 in abs(complex) approximation */ + } + + valley_amp = peak_amp; move16(); + FOR(i = 0; i < n_ind; i++) + { + valley_amp = s_min(x_abs[i], valley_amp); + } + + /* at least a localized amplitude ratio of 16 (24 dB) required to declare a pure noise-free sinusoid */ + if (sub(shr(peak_amp, 4), valley_amp) < 0) /* 1/16 */ + { + nonpure_tone_detect = s_or(nonpure_tone_detect, 0x02); /* not a pure tone due to too low local SNR P2V */ + } + } + + + /* analyze LF/ HF bands energy dynamics vs the assumed single tone band ( for one or two peaks found cases ) */ + { + /* Xavg , is a vector of rather rough MDCT based band amplitude estimates in perceptually motivated bands. from approx the last 26 ms of synthesis */ + + /* eval amplitude relations for assumed tonal band vs lower and higher bands */ + /*N_grp = xavg_N_grp[fs_idx];*/ /* { 4 NB , 5 WB , 6 SSWB , 7 SWB, 8 FB }; */ + N_grp = add(fs_idx, 4); + assert(fs_idx < 5); + + + /* establish band(s) with assumed sinusoid tone */ + /* if tone freq location is below first MDCT-band definition, use first band as band location anyway */ + + /* band 0 , 1 , 2 , 3 , ...*/ + /* dct-inds "c" "0"...11, 12...19, 20...35, 36 ... */ + /* gwplr_fx= [ 1 , 12(750Hz), 20(1250Hz) , 36 , ... */ /* lowest lim+1 in gwplr */ + + /* for-loop BASOP version */ + tmp = 0; move16(); + gwlpr_fxPlus1 = &(gwlpr_fx[1]); /* ptr init */ + FOR(i = 0; i < N_grp; i++) + { + if (sub(plocs[tone_ind], gwlpr_fxPlus1[i]) >= 0) + { + tmp = add(i, 1); + } + } + + sineband_ind_low = tmp; move16(); + sineband_ind_high = tmp; move16(); /* typically in the same band as low */ + + /* a single tone may end up on a band border + , handle case when assumed tone is more or less right in-between two perceptual bands +/- 4*62.5 Hz */ + + test(); logic16(); + if ((sineband_ind_high > 0) && + (sub(sub(plocs[tone_ind], ONE_SIDED_SINE_WIDTH), gwlpr_fx[add(sineband_ind_high, 1)]) >= 0) + ) + { + sineband_ind_low = sub(sineband_ind_high, 1); + } + + logic16(); + if ((sub(sineband_ind_low, sub(N_grp, 1)) < 0) && + (sub(add(plocs[tone_ind], ONE_SIDED_SINE_WIDTH), gwlpr_fx[add(sineband_ind_low, 1)]) >= 0) + ) + { + sineband_ind_high = add(sineband_ind_low, 1); + } + } + + /* intraframe(26 ms), weighted LB and HB envelope dynamics/variation analysis */ + /* envelope analysis , + require at least two HF or two LF bands in the envelope taper/roll-off analysis , otherwise skip this condition */ + + logic16(); + test(); logic16(); + IF( (nonpure_tone_detect == 0) && + ( (sub( add(sineband_ind_high, 2), N_grp) < 0 ) || + (sub(sineband_ind_low, 2+1 ) >= 0) + ) + ) + { + + /* delta taper-off analysis solution, less sensitive to input bandwidth limitation and levels */ + + /* test Xavg Word16 result above vs a high resolution Word32 L_Xavg */ + /* strong spectral tilt causes HF to be truncated in Word16 */ + + basop_memcpy(L_XavgUp_fx, L_Xavg, N_grp * sizeof(Word32) ) ; + + /* first remove all energy from the assumed tonal peak band(s) */ + L_XavgUp_fx[sineband_ind_low] = L_min(L_XavgUp_fx[sineband_ind_low], 1); move32(); + L_XavgUp_fx[sineband_ind_high] = L_min(L_XavgUp_fx[sineband_ind_high], 1); move32(); + + tmp = getScaleFactor32_0(L_XavgUp_fx, N_grp); /* o: measured headroom in range [0..32], 32 if all L_x[i] == 0 */ + if (sub(tmp, 32) == 0) + { + nonpure_tone_detect = s_or(nonpure_tone_detect, 0x100); /* also set a flag for an all zero L_Xavg coarse spectrum estimate signal */ + } + + + /* add noise floor to L_Xavg before log2 function call */ + L_nf = L_shl(1L, sub(tmp, 1)); + L_nf = L_max(L_nf, 1L); + for (i = 0; i < N_grp; i++) + { + L_XavgUp_fx[i] = L_shl_sat(L_XavgUp_fx[i], tmp); move32(); /* maximize precision before actual log2_fx(Word32) calc call */ + + L_tmp = L_XavgUp_fx[i]; move32(); + test(); + if (L_tmp <= 0) + { + L_tmp = L_nf; move32(); + } + + /* log2(Upshifted Word32) */ + /* maximize precision in BASOP Log2 function */ + L_XavgL2_fx[i] = BASOP_Util_Log2_lc3plus(L_tmp); /* L_input 1.0 or lower --> output always negative */ + /* add 31.0 to store as fractional bits of an upscaled positive Word32 integer input ) */ + L_XavgL2_fx[i] = L_add(31L << 25, L_XavgL2_fx[i]); /* only diffs added so 31.0 is cancelled out later , in total only values between +/- 2^6 = [-64 ... -64[ are possible */ + } /* band i for L_Xavg calc*/ + /* verify that an assumed clean sine does not have any odd HF content indications by thresholding the accumulated delta rise in LF/HF side lobes */ + L_Ltot_inc_HF = 0; move32(); + for (i = (sineband_ind_high + 1); i < (N_grp - 1); i++) + { + L_tmp_dB = 0; move32(); + if (L_sub(L_Xavg[i], L_Xavg[i + 1]) < 0) /* only increases are accumulated */ + { + L_tmp_dB = L_sub(L_XavgL2_fx[i + 1], L_XavgL2_fx[i]); /* obtain ratio in log2 domain */ + } + L_tmp = Mpy_32_16_lc3plus(L_tmp_dB, scATHFx[i]); /* scATHFx[i] is the ATH weight for band i and band i+1 */ + L_tmp = L_shr_pos(L_tmp, 1); /* Q25 -> Q24 */ + + L_Ltot_inc_HF = L_add(L_Ltot_inc_HF, L_tmp); /* Q24 */ + } + + /* verify that an assumed clean sine does not have any odd LF content by thresholding the accumulated LF reverse up tilt */ + + L_Ltot_inc_LF = 0; move32(); + tmp = s_max(0, sub(sineband_ind_low, 1)); /* could also be pointer init */ + for (i = tmp; i > 0; i--) + { + L_tmp_dB = 0; move32(); + if (L_sub(L_Xavg[i - 1], L_Xavg[i]) > 0) /* only increases are accumulated */ + { + L_tmp_dB = L_sub(L_XavgL2_fx[i - 1], L_XavgL2_fx[i]); /* obtain ratio in log2 domain */ + } + L_tmp = Mpy_32_16_lc3plus(L_tmp_dB, scATHFx[i-1]); /* scATHFx[i-1] is the ATH weight in between band i-1 and band i */ + L_tmp = L_shr_pos(L_tmp, 1); /* Q25 -> Q24 */ + L_Ltot_inc_LF = L_add(L_Ltot_inc_LF, L_tmp); /* Q24 */ + } + + if (L_sub(L_Ltot_inc_HF, SIDE_LIM) > 0) /* side_lim=round(Q24x*0.7474) */ + { + /* 4.5 dB in log2 is 0.7474 */ + nonpure_tone_detect = s_or(nonpure_tone_detect, 0x10); /* still not a pure tone, too great HF side increase */ + } + + if (L_sub(L_Ltot_inc_LF, SIDE_LIM) > 0) /* side_lim=round(Q24x*0.7474) */ + { + /* 4.5 dB in log2 is 0.7474 */ + nonpure_tone_detect = s_or(nonpure_tone_detect, 0x20); /* still not a pure tone, too great HF side increase */ + } + + /* verify that an assumed clean sine does not have any odd LF+HF content by thresholding the accumulated LF+HF unexpected tilt */ + if (L_sub(L_add_sat(L_Ltot_inc_LF, L_Ltot_inc_HF), LFHF_LIM) > 0) /* side_lim=round(Q24x*0.7474) */ + { + /* 6.0 dB in log2 is 0.996578428 */ + nonpure_tone_detect = s_or(nonpure_tone_detect, 0x40); /* still not a pure tone, too great LF+HF side increase */ + } + + } /* bands available*/ + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + + return nonpure_tone_detect; + } +#endif /* CR8_A_PLC_FADEOUT_TUNING plc_phecu_non_pure_ana_fx */ + + + + diff --git a/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c b/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c new file mode 100644 index 000000000..50b694e5c --- /dev/null +++ b/lib_lc3plus/plc_phecu_lf_peak_analysis_fx.c @@ -0,0 +1,202 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void plc_phEcu_LF_peak_analysis_fx(Word16 * plocs, /* i/o 0 ... Lprot/2 +1*/ + Word16 * n_plocs, /* i/o 0.. MAX_PLOCS */ + Word32 * L_f0estQ16, /* i/o Q16*/ + const Word16 *mag, /* i: Qx */ + const Word16 stPhECU_f0hzLtpBinQ7, const Word16 stPhECU_f0gainLtpQ15, + const Word16 nSubm, Word16 maxPlocs, + Word8 *scratchBuffer /* Size = 6 * MAX_PLOCS + 42 */ +) + +{ + Counter i, j; + Word16 n_plocs_ana, peakLF_Xval, tmp, f_abs_ind, plocsIntersectFlag; + + Word32 L_fQ7, *L_f0est_prelQ16; + Word16 num_prel = 0, *plocs_prel; + Word16 prel_low, prel_high, start, fin; + Word16 *plocs_old; + Word32 *L_plocsi_old; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("plc_phEcu_LF_peak_analysis_fx", sizeof(struct { + Counter i, j; + Word16 n_plocs_ana, peakLF_Xval, tmp, f_abs_ind, plocsIntersectFlag; + Word32 L_fQ7, *L_f0est_prelQ16; + Word16 num_prel, *plocs_prel; + Word16 prel_low, prel_high, start, fin; + Word16 *plocs_old; + Word32 *L_plocsi_old; + })); +#endif + + + + L_f0est_prelQ16 = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 4 * 7 */ + plocs_prel = (Word16 *)scratchAlign(L_f0est_prelQ16, sizeof(*L_f0est_prelQ16) * 7); /* Size = 2 * 7 */ + plocs_old = (Word16 *)scratchAlign(plocs_prel, sizeof(*plocs_prel) * 7); /* Size = 2 * MAX_PLOCS */ + L_plocsi_old = (Word32 *)scratchAlign(plocs_old, sizeof(*plocs_old) * maxPlocs); /* Size = 4 * MAX_PLOCS */ + + test(); test(); + IF ((*n_plocs > 0) && sub(stPhECU_f0gainLtpQ15, ((Word16)(0.25 * 32768.0))) > 0 && + sub(stPhECU_f0hzLtpBinQ7, (Word16)(2.75 * 128.0)) < 0) + { + + /* % analyze/apply f0Ltp to avoid intermodulation effects below f0 of ~180 Hz + % we only do the f0Ltp-replacement(s) if there is already an established + % fft peak in the region ~fRes to 2.5*fres + fft_peak_eval_plocs = 1:3; + plocsIntersectFlag = intersect(plocs, fft_peak_eval_plocs ); % check for 1,2,3 in plocs */ + + plocsIntersectFlag = 0; move16(); + peakLF_Xval = 0; move16(); + n_plocs_ana = s_min(*n_plocs, 3); + FOR (i = 0; i < n_plocs_ana; i++) + { + tmp = plocs[i]; move16(); + if (sub(tmp, 2) <= 0) /* C index 0, 1,2 checked , [DC, 62.5 Hz, 125Hz ] */ + { + plocsIntersectFlag = add(i, 1); + } + peakLF_Xval = s_max(mag[tmp], peakLF_Xval); + } + + num_prel = 0; move16(); + IF (plocsIntersectFlag != 0) + { /* fft-peak at 0, 62 or 125 Hz */ + /* analyze if ltp-based f0 need to be added or not */ + peakLF_Xval = mult_r(peakLF_Xval, (Word16)(.375 * 32768.0)); /* now as a limit */ + + FOR (i = 1; i <= nSubm; i++) + { + L_fQ7 = L_mult0(i, stPhECU_f0hzLtpBinQ7); /* fractional index stored in L_plocsi */ + f_abs_ind = L_shr_pos(L_add(L_fQ7, 64), 7); /* integer bin index stored in plocs */ + + test(); + IF ((L_sub(L_fQ7, 819) <= 0) && /* % only apply up to ~400hz , 819 = 400/62.5*128 */ + (sub(mag[f_abs_ind], peakLF_Xval) > + 0)) /* % only set as preliminary if relative peak strength is signficant*/ + { + L_f0est_prelQ16[num_prel] = L_shl_pos(L_fQ7, 9); move32(); + plocs_prel[num_prel] = f_abs_ind; move16(); + num_prel = add(num_prel, 1); + } + } + } /*intersectFlag*/ + + /* now replace/ merge new preliminary added peaks with existing plocs and L_f0estQ16 */ + /* note that a previous fake/merged magnitude-determined peak may be replaced by two separated side peaks */ + + /* a general non-optimized list-merging solution below */ + test(); + IF ((num_prel > 0) && (sub(add(num_prel, *n_plocs), MAX_PLOCS) <= 0) /* skip in case plocs list is too large */ + ) + { + prel_low = plocs_prel[0]; move16(); + prel_high = plocs_prel[sub(num_prel, 1)]; move16(); + + /* initial assumption:: all original peaks (1 or 2 of them) are positioned below prel_low */ + start = (*n_plocs); /* at this point 'start' is the location_c where to add any harmonics peaks */ + + FOR (i = sub(*n_plocs, 1); i >= 0; i--) + { + if (sub(plocs[i], prel_low) >= 0) + { + start = i; move16(); + } + } + start = sub(start, 1); /* end of old section to copy before the added/merged section */ + start = s_max(start, -1); /* limit for loop later */ + /*% dbg check low part for a sucessful replace/merge */ + if (start >= 0 && start < *n_plocs) + { + ASSERT(plocs[start] < plocs_prel[0]); + } + + sub(0, 0); + IF (prel_high < plocs[0]) + { + fin = 0; move16(); /*% keep all plocs , just concat */ + } + ELSE + { + fin = *n_plocs; + FOR (i = 0; i < *n_plocs; i++) + { + sub(0, 0); + if (plocs[i] <= prel_high) + { + fin = i; move16(); + } + } + fin = add(fin, 1); /* first element in high part of old plocs to be copied */ + } + + /*% dbg check high part for a sucessful replace/merge */ + if (fin >= 0 && fin < *n_plocs) + { + ASSERT(plocs_prel[sub(num_prel, 1)] < plocs[fin]); + } + + /* + % actual replace/merge of added integer locations and fractional freqs. into plocs/f0list list ; + % three loops in BASOP + plocs = [ plocs(1:(start)) ; plocs_prel ; plocs((fin):end) ]; + f0est = [ f0est(1:(start)) ; f0est_prel; f0est((fin):end) ]; + */ + + FOR (i = 0; i < *n_plocs; i++) + { + plocs_old[i] = plocs[i]; move16(); + L_plocsi_old[i] = L_f0estQ16[i]; move32(); + } + + /* + j=0; + FOR(i=0; i <= start; i++) + { + plocs[i] = plocs_old[i]; move16(); + L_f0estQ16[i] = L_plocsi_old[i]; move32(); + j++; + } + */ + + j = add(start, 1); + + ASSERT(j>=0); + + FOR (i = 0; i < num_prel; i++) /* NB this section may both insert or overwrite old plocs */ + { + plocs[j] = plocs_prel[i]; move16(); + L_f0estQ16[j] = L_f0est_prelQ16[i]; move32(); + j++; + } + FOR (i = fin; i < *n_plocs; i++) /* copy the tail of the list */ + { + plocs[j] = plocs_old[i]; move16(); + L_f0estQ16[j] = L_plocsi_old[i]; move32(); + j++; + } + + *n_plocs = j; move16(); /* update total length */ + } /* num_prel >0*/ +} /* gain/hz Limits */ + +#ifdef DYNMEM_COUNT +Dyn_Mem_Out(); +#endif + +} + + diff --git a/lib_lc3plus/plc_phecu_peak_locator_fx.c b/lib_lc3plus/plc_phecu_peak_locator_fx.c new file mode 100644 index 000000000..531ee8f6f --- /dev/null +++ b/lib_lc3plus/plc_phecu_peak_locator_fx.c @@ -0,0 +1,385 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +#define RES_fx 1 /* fixed point resolution */ + +/*----------------------------------------------------------------------------- + * peak_locator_fx() + *----------------------------------------------------------------------------*/ +void plc_phEcu_peak_locator_fx(const Word16 *inp, /* i: vector with values >=0 ,Qx */ + const Word16 inp_len, /* i: length of inp */ + Word16 * int_plocs, /* o: array of filtered integer plocs Q0 */ + Word16 * n_fsc, /* o: total_ number of filtered located highs Q0 */ + const Word16 sens, /* i sensitivity, Qx */ + const Word16 inp_high, /* i global high , Qx */ + const Word16 inp_low, /* i: global low, Qx */ + Word16 maxLprot_Red, /* i: optional size for wc memory alloc of scratch buffer */ + Word8 *scratchBuffer /* i: : scratch buffer 2* 3*(1+1+(maxLprot_Red/2)+1) */ +) +{ + Counter j, k, n, idx_high, idx_low; + Word16 inp_len_minus1 ; + Word16 pairs_start, pairs_end; + Word16 *p_tmp; + Word16 prev_delta, curr_delta; + Word16 delta_predc, delta_fin; + Word16 add_dc_flag, add_fin_flag; + Word16 low_val_cand_pairs, val_range; + Word16 num_pairs, n_tail_values; + Word16 cand_phase_start, cand_idx, prev_low_plus_sens, tmp; + + Word16 cand_high, prev_low; + Word16 *sc_idx; /* 1+ 128/2+1, or 1+ 256/2+1 ... 1+ 640/2+1 or 1+ 768/2+1*/ + Word16 *cand_pairs_buf ; /* actually lowVal + [DC ] + (368/2)pairs + [FS/2] */ + Word16 *cand_pairs; /* actually [DC ] + pairs + [FS/2] */ + Word16 * fsc_idx; /* list of high locations in sc__idx 1+368/2+1 */ + + + + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("peak_locator_fx", sizeof(struct { + Counter j, k, n, idx_high, idx_low; + Word16 inp_len_minus1; + Word16 pairs_start, pairs_end; + Word16 *p_tmp; + Word16 prev_delta, curr_delta; + Word16 delta_predc, delta_fin; + Word16 add_dc_flag, add_fin_flag; + Word16 low_val_cand_pairs, val_range; + Word16 num_pairs, n_tail_values; + Word16 cand_phase_start, cand_idx, prev_low_plus_sens, tmp; + Word16 cand_high, prev_low; + Word16 *sc_idx; + Word16 *cand_pairs_buf; + Word16 *cand_pairs; + Word16 *fsc_idx; + })); +#endif +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::peak_locator_fx(1st)"); +#endif + sc_idx = (Word16 *)scratchAlign(scratchBuffer, 0); /* ByteSize = 2 * (1+ inp_len+1) */ + cand_pairs_buf = (Word16 *)scratchAlign(sc_idx, sizeof(*sc_idx) * (1+inp_len+1)); /* ByteSize = 2 * (1+ 1+ inp_len+1 ) */ + fsc_idx = (Word16 *)scratchAlign(cand_pairs_buf , sizeof(*cand_pairs_buf) * (1+ 1+ inp_len+1)); /* ByteSize = 2 * ( 1+ inp_len + 1) */ + ASSERT((4 * maxLprot_Red) >= 3 * (1 + 1 + inp_len + 1)); /* basic buffer check */ + UNUSED(maxLprot_Red); + + inp_len_minus1 = sub(inp_len, 1); /* size of delta=derivative array ,and last index in inp */ + + cand_pairs = &cand_pairs_buf[1]; /* ptr init , make space for storing a lowest amplitude value in location -1 */ + pairs_start = 1; move16(); /* adjusted to zero or 1 or 2 when/if, DC is injected as sc_idx[0], or initial plateau skipped */ + + p_tmp = &(sc_idx[pairs_start]); /* ptr init */ + + + /* xor high/low pairs of delta_inp and save sign changes */ + prev_delta = sub(inp[1], inp[0]); /* precompute very first delta */ + + FOR(n = 1; n < inp_len_minus1; n++) + { /* sign change analysis */ + curr_delta = sub(inp[n + 1], inp[n]); /* n+1 ,n , are loop ptrs */ + if (s_xor(prev_delta, curr_delta) < 0) /* a "0" delta treated as a positive sign */ + { + *p_tmp++ = n; move16(); /* store sign change bin locations , location n in the inp[] signal */ + } + prev_delta = curr_delta; move16(); + } + + L_sub(0, 0); /* account for length calculaton */ + k = (Word16)(p_tmp - &(sc_idx[pairs_start])); + + + /* copy sign change location values to a pairs array */ + /* leave one initial sc_idx location open for a potential initial DC value */ + + ASSERT(pairs_start >= 0 && ((k - 1) + pairs_start) < (inp_len +2)); + FOR(j = 0; j < k; j++) + { + cand_pairs[j + pairs_start] = inp[sc_idx[j + pairs_start]]; move16(); move16(); /* the indirect should be calculated */ + } + + + /* filter away a potential single initial/trailing plateau + to enable correct analysis for adding DC or fs/2 bins */ + + logic16(); + IF((sub(k, 2) >= 0) && + (sub(cand_pairs[pairs_start], cand_pairs[pairs_start + 1]) == 0)) + { + pairs_start = add(pairs_start, 1); + k = sub(k, 1); + } + + /* filter away potential single trailing plateu */ + pairs_end = sub(add(pairs_start,k), 1); /* point to last established sign change element */ + logic16(); + if ((sub(k, 2) >= 0) && + (sub(cand_pairs[sub(pairs_end,1)], cand_pairs[pairs_end]) == 0)) + { + k = sub(k, 1); + } + pairs_end = sub(add(pairs_start,k), 1); /* recalc ptr to last element */ + + + /* conditionally add high/lows on both sides of input (pre_dc or fin) as candidates */ + add_dc_flag = 0; move16(); + add_fin_flag = 0; move16(); + + + IF(sub(k, 1) == 0) /* one single sign change found special case */ + { + if (sub(inp[0], cand_pairs[pairs_start]) != 0) + { + add_dc_flag = 1; move16(); /* not plateau */ + } + + if (sub(cand_pairs[pairs_end], inp[inp_len_minus1]) != 0) + { + add_fin_flag = 1; move16(); /* not plateau */ + } + } + + IF(sub(k, 2) >= 0) + { + delta_predc = sub(cand_pairs[pairs_start + 1], cand_pairs[pairs_start]); + delta_fin = sub(cand_pairs[pairs_end], cand_pairs[pairs_end - 1]); + + /* plateaus are allowed to be detected by xor sign change, + but still not allowed at the start nor at the end */ + + add_dc_flag = 1; move16(); + if (sub(inp[0], cand_pairs[pairs_start]) == 0) + { + add_dc_flag = 0; move16(); /* plateau down or , plateus up., --> do not add DC */ + } + + logic16(); + if ((sub(inp[0], cand_pairs[pairs_start]) < 0) && (delta_predc > 0)) + { + add_dc_flag = -1; move16(); /*UP - up ... replace */ + } + logic16(); + if ((sub(inp[0], cand_pairs[pairs_start]) > 0) && (delta_predc < 0)) + { + add_dc_flag = -1; move16(); /* DOWN - down ... % replace */ + } + + add_fin_flag = 1; move16(); + if (sub(cand_pairs[pairs_end], inp[inp_len_minus1]) == 0) + { + add_fin_flag = 0; move16(); /* up - plateau ... */ + } + logic16(); + if ((delta_fin > 0) && (sub(cand_pairs[pairs_end], inp[inp_len_minus1]) < 0)) + { + add_fin_flag = -1; move16(); /* up - UP ... % replace , hard to hit */ + } + logic16(); + if ((delta_fin < 0) && (sub(cand_pairs[pairs_end], inp[inp_len_minus1]) > 0)) + { + add_fin_flag = -1; move16(); /*down - DOWN ... % replace */ + } + + } + + IF(add_dc_flag > 0) + { /* add DC */ + pairs_start = sub(pairs_start, 1); + cand_pairs[pairs_start] = inp[0]; move16(); + sc_idx[pairs_start] = 0; move16(); + ASSERT(pairs_start >= 0 && pairs_start <= 2); + k = add(k, 1); + } + IF(add_dc_flag < 0) + { /* -1 --> replace with DC*/ + cand_pairs[pairs_start] = inp[0]; move16(); + sc_idx[pairs_start] = 0; move16(); + ASSERT(pairs_start >=0 && pairs_start <= 2); + } + + IF(add_fin_flag > 0) + { /* add FS/2 */ + pairs_end = add(pairs_end, 1); + cand_pairs[pairs_end] = inp[inp_len_minus1]; move16(); + sc_idx[pairs_end] = inp_len_minus1; move16(); + k = add(k, 1); + } + IF(add_fin_flag < 0) + { /* -1, replace tail with FS/2*/ + cand_pairs[pairs_end] = inp[inp_len_minus1]; move16(); + sc_idx[pairs_end] = inp_len_minus1; move16(); + } + /* preliminary cand_pairs now only have highs , lows , no initial/trailing plateaus */ + + + /* we allow the DC/FsBy2 lows to be used as the candidatelLow */ + low_val_cand_pairs = inp_low; move16(); + val_range = sub( inp_high, low_val_cand_pairs); /* used to determine if search is useful at all */ + + logic16(); + if ((sub(val_range, RES_fx) < 0) || + (sub( inp_high, sens) < 0)) + { + k = 0; move16(); + } + + logic16(); + if ((k == 0) && (sub(val_range, sens) >= 0)) + { + k = 1; move16(); + } + + + IF(sub(k, 2) > 0) + { + /* low, high, low, ... or + high, low, high, ...*/ + + cand_phase_start = pairs_start; move16(); /*assume first candidate is a high */ + if (sub(cand_pairs[pairs_start], cand_pairs[pairs_start + 1]) < 0) + { + cand_phase_start = add(pairs_start, 1); /* first is a low, --> skip to next higher cand */ + } + + /* high, low, high, ... */ + tmp = k; move16(); + if (sub(cand_phase_start, pairs_start) != 0) + { + tmp = sub(tmp, 1); + } + num_pairs = shr(tmp, 1); + n_tail_values = sub(tmp, shl(num_pairs, 1)); + + /* filter preliminary sign changes into sensitivity filtered sign changes */ + + *n_fsc = 0; move16(); /* counter of filtered fsc_idx */ + cand_high = low_val_cand_pairs; move16(); + cand_idx = -1; move16(); /* sentinel location for no high cand found yet. */ + cand_pairs[-1] = low_val_cand_pairs; move16(); + + prev_low = low_val_cand_pairs; move16(); + prev_low_plus_sens = add(prev_low, sens); + + /* filter loop for high - low sign change pairs */ + /* idx_high, idx_low are raw pointers into the cand_pairs and sc_idx arrays */ + + FOR( idx_high = cand_phase_start; idx_high < (cand_phase_start + 2 * num_pairs); idx_high += 2) + { + idx_low = idx_high+1; /* loop ptr increase */ + + /* new high candidate larger than previous candidate and */ + /* sensitivity still larger than the the previous low */ + tmp = s_max(cand_high, prev_low_plus_sens); + if(sub(cand_pairs[idx_high], tmp) > 0) + { + cand_idx = idx_high; move16(); /* enable or shift candidate position fwd */ + } + cand_high = cand_pairs[cand_idx]; move16(); /* NB, cand_pairs[-1] , has the low_val_cand_pairs value stored */ + + /* now check the fwd idx_low of the current {high,low} pair */ + prev_low = s_min(cand_pairs[idx_low], prev_low); + + tmp = sub(cand_high, sens); + IF(sub(tmp, cand_pairs[idx_low]) > 0) + { + /* this low point is now low enough to fix a previous high candidate */ + + fsc_idx[*n_fsc] = cand_idx; move16(); /*% add cand high idx -> output idx list*/ + *n_fsc = add(*n_fsc, 1); + + prev_low = cand_pairs[idx_low]; move16(); /* use this value as new low estimate */ + cand_idx = -1; move16(); /* no candidate until next pair or tail bin, and pt to lowVal */ + cand_high = low_val_cand_pairs; move16(); /* enable next candidate to be selected immediately */ + } + prev_low_plus_sens = add(prev_low, sens); + } /* { high, low} FOR loop */ + + logic16(); + IF((n_tail_values == 0) && (cand_idx >= 0)) + { + /* no tail low or high value to analyze + still may need to lock a non-locked but qualified candidate */ + fsc_idx[*n_fsc] = cand_idx; move16(); + *n_fsc = add(*n_fsc, 1); + } + + + /* cand_pairs vector may have a last orphan value */ + IF(n_tail_values > 0) + { + /* cand_pairs vector may have a last orphan tail value */ + /* + logic boils down to if (nTailValues > 0) && (cand_pairs(n_end) > tmp) + there is a last one trailing high to process + + a) the last high, may be a new high Peak if we have not yet + locked the current candidate + b) if we have locked the last candidate, the last high may also be + a highpeak if it is high enough from the(newly set previous) valley floor. + + tmp=a||b + */ + + tmp = s_max(cand_high, prev_low_plus_sens); + tmp = sub(cand_pairs[pairs_end], tmp); + IF(tmp > 0) + { + fsc_idx[*n_fsc] = pairs_end; move16(); + *n_fsc = add(*n_fsc, 1); + } + ELSE + { + IF(cand_idx >= 0) + { /* we have a previously established high candidate */ + fsc_idx[*n_fsc] = cand_idx; move16(); + *n_fsc = add(*n_fsc, 1); + } + + } + } + /* move high locations info from fsc_idx , to output */ + FOR(j = 0; j < *n_fsc; j++) + { + ASSERT(fsc_idx[j] >= 0 && fsc_idx[j] < (inp_len+2)); + int_plocs[j] = sc_idx[fsc_idx[j]]; move16(); move16(); /* the indirect moves are calculated */ + } + + } /* end of pairs + [tail] section filtering */ + ELSE + { + /* constant/single rise or constant decay or very low overall values, cases */ + *n_fsc = 0; move16(); + + logic16(); + tmp = sub(inp_high, sens); + IF((k != 0) && (sub(tmp, low_val_cand_pairs) > 0)) + { + /* low,high */ + /* high,low */ + tmp = plc_phEcu_find_ind_fx(inp, inp_len, inp_high); move16(); + int_plocs[0] = tmp; move16(); /* simply locate the high peak*/ + *n_fsc = 1; move16(); + if (tmp < 0) + { /*safety in case max value index was not found */ + *n_fsc = 0; move16(); + } + } + } +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} + diff --git a/lib_lc3plus/plc_phecu_setf0hz_fx.c b/lib_lc3plus/plc_phecu_setf0hz_fx.c new file mode 100644 index 000000000..6fffe632c --- /dev/null +++ b/lib_lc3plus/plc_phecu_setf0hz_fx.c @@ -0,0 +1,60 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +/* +st_PhECU_f0minLtp=55; % 55.4 Hz +st_PhECU_f0maxLtp=376; % 376.4706 Hz + +*/ + + +Word16 +plc_phEcuSetF0Hz_fx(/* output Q7 bin frequency [0.. 255.xxxx] "1 sign, 8 bits mantissa, 7 binomial" [0-255.9999] */ + Word16 fs_idx, Word16 old_pitch_int, Word16 old_pitch_fr) +{ + Word16 pitch_lagQ2, result, expo; + Word32 L_result, L_tmp; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("plc_phEcuSetF0Hz_fx", sizeof(struct { + Word16 pitch_lagQ2, result, expo; + Word32 L_result, L_tmp; + Word16 num_FsByResQ0[5]; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::plc_phEcuSetF0Hz_fx"); +#endif + + result = 0; move16(); + IF (old_pitch_int != 0) + { + pitch_lagQ2 = add( + old_pitch_fr, + shl(old_pitch_int, 2)); /* lag at the current fs_idx , max lag_value is is 228(+.75)*48/12.8 = 858 in Q0 */ + + L_result = plc_phEcu_ratio_fx(L_deposit_h(num_FsByResQ0[fs_idx]), L_deposit_h(pitch_lagQ2), &expo); + L_tmp = L_shl_sat(L_result, sub(11, expo)); /* move to Q7, in high word to allow round*/ + result = round_fx(L_tmp); + } +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + + return result; /*Q7*/ +} + + diff --git a/lib_lc3plus/plc_phecu_tools_fx.c b/lib_lc3plus/plc_phecu_tools_fx.c new file mode 100644 index 000000000..13e90fa49 --- /dev/null +++ b/lib_lc3plus/plc_phecu_tools_fx.c @@ -0,0 +1,247 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +/* initilize a short vector */ +void plc_phEcu_initWord16(Word16 * vec, /*i/o : short vector pointer */ + const Word16 value, /*i : short initialization value */ + const Word16 len) /*i : number of elements */ +{ + Counter n; + + FOR (n = 0; n < len; n++) + { + vec[n] = value; move16(); + } +} + +/* scale inplace with allowed saturation in upscaling , function not available in basop_util */ +void Scale_sig_sat(Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Counter i; + Word16 tmp; + IF (exp0 > 0) + { + FOR (i = 0; i < lg; i++) + { + x[i] = shl_sat(x[i], exp0); move16(); /* no saturation warnings triggered here */ + } + return; + } + IF (exp0 < 0) + { + tmp = shl(-32768, s_max(exp0, -15)); /* we use negative to correctly represent 1.0 */ + FOR (i = 0; i < lg; i++) + { + x[i] = msu_r(0, x[i], tmp); move16(); /* msu instead of mac because factor is negative */ + } + return; + } +} + +void plc_phEcu_minval_fx(const Word16 *inp, /* i : vector */ + const Word16 len, /* i : length */ + Word16 *minvalPtr /* o : min value Ptr */ +) +{ + Word16 minTmp; + Counter pos; + + minTmp = inp[0]; move16(); + assert(len>1); + FOR (pos = 1; pos < len; pos++) + { + minTmp = s_min(inp[pos], minTmp); + } + + *minvalPtr = minTmp; move16(); +} + +void plc_phEcu_maxval_fx(const Word16 *inp, /* i : vector */ + const Word16 len, /* i : length */ + Word16 *maxvalPtr /* o : *maxvalPtr */ +) +{ + Word16 maxTmp; + Counter pos; + + maxTmp = inp[0]; move16(); + + assert(len>1); + FOR (pos = 1; pos < len; pos++) + { + maxTmp = s_max(inp[pos], maxTmp); + } + *maxvalPtr = maxTmp; move16(); +} + +/* in case a value (e.g max or min) is already known , find the first corresponding array index */ +Word16 plc_phEcu_find_ind_fx( /* o : output maximum indx 0.. len-1 */ + const Word16 *inp, /* i : vector */ + const Word16 len, /* i : length */ + const Word16 val /* i : value to find */ +) +{ + Word16 val_ind; + Counter pos; + + val_ind = -1; move16(); + + FOR(pos = 0; pos < len; pos++) + { + if (sub(inp[pos], val) == 0) + { + val_ind = pos; move16(); + } + } + return val_ind; +} + +/*----------------------------------------------------------------------------- + * ratio_fx() + * + * Divide the numerator by the denominator. + *----------------------------------------------------------------------------*/ +Word16 plc_phEcu_ratio_fx( /* o : quotient in Q14 */ + const Word32 numer, /* i : numerator */ + const Word32 denom, /* i : denominator */ + Word16 *expo) /* o : req shift of quotient */ +{ + Word16 expNumer, expDenom; + Word16 manNumer, manDenom; + Word16 quotient; +#ifdef DYNMEM_COUNT + Dyn_Mem_In("plc_phEcu_ratio_fx", sizeof(struct { + Word16 expNumer, expDenom; + Word16 manNumer, manDenom; + Word16 quotient; + })); +#endif + + 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_pos(manNumer, 1); /* Ensure the numerator < the denominator */ + quotient = div_s(manNumer, manDenom); /* in Q14 */ + + *expo = sub(expNumer, expDenom); +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + return quotient; /* Q14 */ +} + +Word32 winEnCalc( /* o: output summed energy Ltot */ + const Word16 *x, /* i: Input signal */ + const Word16 headroom_shift, /* i: headroom_shift */ + const Word16 *win, /* i: left side Window coefficients */ + const Word16 rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */ + const Word16 halfLength, /* i: Half of the total length of a complete Hamming window. */ + Word16 *exp /* i/o : i exp of Word16 variable x , o:Lexp of output Word32 sum */ + ) +{ + Counter i; + Word32 L_tot; + const Word16 *pX, *pW; + Word16 tmp, tmp_RL; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("PhEcu::GF::winEnCalc", sizeof(struct { + Counter i; + Word32 L_tot; + const Word16 *pX, *pW; + Word16 tmp, tmp_RL; + })); +#endif + + +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::winEnCalc"); +#endif + + L_tot = INT32_MAX; move32(); /*acc is on negative side , but as all accumulation is positive, we make use of one extra bit */ + pX = x; + pW = win; + + + assert( headroom_shift>=0 ); + FOR (i = 0; i < halfLength; i++) /* 1st symmetric half of the Hamming window */ + { + tmp = mult(*pX++, *pW++); + tmp = shr_pos(tmp, headroom_shift); /* shr may/create bias on the negative side , costly options are shr_r or use msu_r */ + L_tot = L_msu0(L_tot, tmp, tmp); /* acc on negative energy side */ + } + + /* Periodic filter - one more rect sample before end tapering */ + tmp_RL = add(rectLength, 1); + ASSERT(rectLength != 0); + + FOR (i = 0; i < tmp_RL; i++) /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */ + { + tmp = shr_pos( *pX++, headroom_shift); + L_tot = L_msu0(L_tot, tmp, tmp); /* acc on negative side */ + } + + tmp_RL = sub(halfLength, 1); + ASSERT(rectLength != 0); + + FOR (i = 0; i < tmp_RL; i++) /* 2nd symmetric half of the Hamming window. */ + { + tmp = mult(*pX++, *(--pW)); + tmp = shr_pos(tmp, headroom_shift); + L_tot = L_msu0(L_tot, tmp, tmp); + } + + /* Lexp = 2*(incoming_exp + dnshift) + 1 , 2x for square + 1(for msu0 DSP dn shift)*/ + *exp = add(shl_pos(add(*exp, headroom_shift),1),1); + + /* handle wrap on zero point */ + IF( L_tot >= 0 ) + { /* L_tot positive --> less than 32 bits needed, */ + L_tot = L_add(L_tot,(INT32_MIN+1)); + if( L_tot == 0 ) + { + *exp = LTOT_MIN_EXP; /* WC is actually (-(15+4)*2 + 1 +1 -31) */ ; move16(); + } + L_tot = L_min(L_tot, -1); /* make sure there is energy for future ratio calculations */ + } + ELSE + { /* L_tot negative --> more than 31 bits needed for sum , scale 32 bit sum within 31 bits and adjust exp */ + + L_tot = L_shr_pos(L_add(L_tot,1),1); /* rnd by adding 1, then use 50% contribution from negative side */ + L_tot = L_add(L_tot, INT32_MIN>>1); /* add 50% contribution from positive side */ + + *exp = add(*exp, 1); move16(); + } + + L_tot = L_max( -(INT32_MAX), L_tot); /* guard against max accumulation on the negative side , should only occur for rectangle windows */ + L_tot = L_negate(L_tot); /* no saturation here */ + + /* activate when xfp_exp is not used any longer */ + /* pre-maximize the mantissa for the following steps in burst_ana_dx */ + tmp = norm_l(L_tot); + L_tot = L_shl(L_tot,tmp); + *exp = sub(*exp, tmp); move16(); + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + + return L_tot; +} + diff --git a/lib_lc3plus/plc_tdac_fx.c b/lib_lc3plus/plc_tdac_fx.c new file mode 100644 index 000000000..c27cc9e7a --- /dev/null +++ b/lib_lc3plus/plc_tdac_fx.c @@ -0,0 +1,217 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +/* + * processTdac_fx + * + * Parameters: + * ola_mem o: pointer of output signal Q0 + * ola_mem_exp o: exponent of output signal Q0 + * synth i: pointer of input signal Q0 + * synth_exp i: exponent of input signal Q0 + * win i: pointer of analysis and synthesis window Q0 + * la_zeroes i: number of zeroes Q0 + * frame_len i: frame length Q0 + * + * Function: + * + * + * Returns: + * void + */ +void processTdac_fx(Word16 *ola_mem, Word16 *ola_mem_exp, const Word16 *synth_inp, const Word16 synth_exp_inp, +#ifdef ENABLE_HR_MODE + const Word32 *win, +#else + const Word16 *win, +#endif + const Word16 la_zeroes, const Word16 frame_len, Word8 *scratchBuffer) +{ + Counter i; + Word16 s; + Word16 L; + Word16 N; + Word16 NZ; + Word16 LD2; + Word32 sz; + Word16 INV_NORM; + Word16 INV_NORM_E; + Word16 smax; + Word16 * synth; + Word16 synth_len; + Word16 synth_exp; +#ifdef ENABLE_HR_MODE + const Word32 *win1, *win2, *win3, *win4; +#else + const Word16 *win1, *win2, *win3, *win4; +#endif + const Word16 *synth1; + const Word16 *synth2; + Word16 * ola_mem1; + Word16 * ola_mem2; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processTdac_fx", sizeof(struct { + Counter i; + Word16 s; + Word16 L; + Word16 N; + Word16 NZ; + Word16 LD2; + Word32 sz; + Word16 INV_NORM; + Word16 INV_NORM_E; + Word16 smax; + Word16 * synth; + Word16 synth_len; + Word16 synth_exp; + const Word16 *win1; + const Word16 *win2; + const Word16 *win3; + const Word16 *win4; + const Word16 *synth1; + const Word16 *synth2; + Word16 * ola_mem1; + Word16 * ola_mem2; + })); +#endif + + synth = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */ + + ASSERT(la_zeroes <= frame_len / 2); + + L = frame_len; move16(); + LD2 = shr_pos(L, 1); + NZ = sub(LD2, la_zeroes); + + /* inverse normalization of sqrt(2/N) inside window */ +#ifdef ENABLE_HR_MODE + IF ((sub(frame_len, 960) == 0) || (sub(frame_len, 720) == 0)) + { + INV_NORM = negate(shl_pos(frame_len, (15 - 10))); + INV_NORM_E = 3; move16(); + } + ELSE +#endif + { + INV_NORM = negate(shl_pos(frame_len, (15 - 9))); + INV_NORM_E = 2; move16(); + if (norm_s(INV_NORM) > 0) + { + INV_NORM = shl_pos(INV_NORM, 1); + INV_NORM_E = 1; move16(); + } + if (sub(frame_len, 120) <= 0) + { + INV_NORM_E = add(INV_NORM_E, 2); + } + if (sub(frame_len, 20) <= 0) + { + INV_NORM_E = add(INV_NORM_E, 2); + } + } + + /* Scale input */ + synth_len = sub(shl_pos(L, 1), la_zeroes); + s = getScaleFactor16(synth_inp, synth_len); + + FOR (i = 0; i < synth_len; i++) + { + synth[i] = shl(synth_inp[i], s); move16(); + } + synth_exp = sub(synth_exp_inp, s); + + /* calculate x_ov[L+la_zeroes] ... x_ov[2*L-1] */ + + win1 = &win[L + LD2 - 1]; + win2 = &win[L + LD2]; + + win3 = &win[LD2 - 1]; + win4 = &win[LD2]; + + synth1 = &synth[L + LD2 - 1 - la_zeroes]; + synth2 = &synth[L + LD2 - la_zeroes]; + + ola_mem1 = &ola_mem[LD2 - la_zeroes]; + ola_mem2 = &ola_mem[LD2 - la_zeroes - 1]; + + smax = 15; move16(); + + FOR (i = 0; i < NZ; i++) + { + /* analysis windowing + 2N -> N */ + sz = L_mac_sat(L_mult(*synth1, extractW16(*win1)), *synth2, extractW16(*win2)); + + /* N -> 2N + synthesis windowing */ + *ola_mem1 = round_fx(Mpy_32_16_lc3plus(sz, extractW16(*win3))); move16(); + *ola_mem2 = round_fx(Mpy_32_16_lc3plus(sz, extractW16(*win4))); move16(); + + /* determine headroom */ + s = norm_s(*ola_mem1); + if (*ola_mem1 != 0) + smax = s_min(smax, s); + s = norm_s(*ola_mem2); + if (*ola_mem2 != 0) + smax = s_min(smax, s); + + /* pointer update */ + win1--; + win2++; + win3--; + win4++; + synth1--; + synth2++; + ola_mem1++; + ola_mem2--; + } + + N = LD2; move16(); + + FOR (; i < N; i++) + { + /* analysis windowing + 2N -> N */ + sz = L_mult(*synth1, extractW16(*win1)); + + /* N -> 2N + synthesis windowing */ + *ola_mem1 = round_fx(Mpy_32_16_lc3plus(sz, extractW16(*win3))); move16(); + + /* determin headroom */ + s = norm_s(*ola_mem1); + if (*ola_mem1 != 0) + smax = s_min(smax, s); + + /* pointer update */ + win1--; + win2++; + win3--; + synth1--; + synth2++; + ola_mem1++; + } + + smax = s_min(smax, 15); + + N = add(N, NZ); + + FOR (i = 0; i < N; i++) + { + ola_mem[i] = round_fx(L_mult(shl(ola_mem[i], smax), INV_NORM)); move16(); + } + + *ola_mem_exp = sub(add(synth_exp, INV_NORM_E), smax); move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/plc_tdc_inverse_odft_fx.c b/lib_lc3plus/plc_tdc_inverse_odft_fx.c new file mode 100644 index 000000000..1e8e3191c --- /dev/null +++ b/lib_lc3plus/plc_tdc_inverse_odft_fx.c @@ -0,0 +1,130 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processInverseODFT_fx(Word32 *r_fx, Word16 *r_fx_exp, Word32 *d2_fx, Word16 d2_fx_exp, Word16 n_bands, + Word16 lpc_order, Word8 *scratchBuffer) +{ + Counter i; + Word16 s; + Word16 n_bands2; + Word32 * x; + const Word32 *inv_odft_twiddle_re; + const Word32 *inv_odft_twiddle_im; + Word8 * buffer_BASOP_rfftN; + + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processInverseODFT_fx", sizeof(struct { + Counter i; + Word16 s; + Word16 n_bands2; + Word32 * x; + const Word32 *inv_odft_twiddle_re; + const Word32 *inv_odft_twiddle_im; + Word8 * buffer_BASOP_rfftN; + Word32 * params[2]; + })); +#endif + + x = scratchAlign(scratchBuffer, 0); /* Size = 320 bytes */ + buffer_BASOP_rfftN = scratchAlign(x, sizeof(*x) * (MAX_BANDS_NUMBER_PLC + MAX_BANDS_NUMBER_PLC/2)); /* Size = 480 bytes */ + + ASSERT(lpc_order <= M); + ASSERT(n_bands == 80 || n_bands == 60 || n_bands == 40 || n_bands == 20); + + n_bands2 = shr_pos_pos(n_bands, 1); + + test(); + IF (sub(n_bands, 20) == 0 || sub(n_bands, 60) == 0) + { + /* sort input samples */ + FOR (i = 0; i < n_bands2; i++) + { + x[2*i] = d2_fx[2 * i]; move32(); + x[2*i+1] = 0; move32(); + x[n_bands + 2*i] = d2_fx[n_bands - 1 - 2 * i]; move32(); + x[n_bands + 2*i + 1] = 0; move32(); + } + BASOP_cfft_lc3plus(&x[0], &x[1], n_bands, 2, &d2_fx_exp, (Word32*)buffer_BASOP_rfftN); + } + ELSE + { + /* sort input samples */ + FOR (i = 0; i < n_bands2; i++) + { + x[i] = d2_fx[2 * i]; move32(); + x[n_bands2 + i] = d2_fx[n_bands - 1 - 2 * i]; move32(); + } + + BASOP_rfftN(x, n_bands, &d2_fx_exp, buffer_BASOP_rfftN); + } + + inv_odft_twiddle_re = inv_odft_twiddle_80_re; + inv_odft_twiddle_im = inv_odft_twiddle_80_im; + IF (sub(n_bands, 20) == 0) + { + inv_odft_twiddle_re = inv_odft_twiddle_20_re; + inv_odft_twiddle_im = inv_odft_twiddle_20_im; + } + ELSE IF (sub(n_bands, 40) == 0) + { + inv_odft_twiddle_re = inv_odft_twiddle_40_re; + inv_odft_twiddle_im = inv_odft_twiddle_40_im; + } + ELSE IF (sub(n_bands, 60) == 0) + { + inv_odft_twiddle_re = inv_odft_twiddle_60_re; + inv_odft_twiddle_im = inv_odft_twiddle_60_im; + } + + s = norm_l(x[0]); + + /* imag[0] is always zero */ + r_fx[0] = L_shl_pos(x[0], s); move32(); + + /* r_fx[0] = r_fx[0] * 1.0001 */ + r_fx[0] = Mpy_32_32_lc3plus(r_fx[0], 0x4001A36E); move32(); + IF (norm_l(r_fx[0]) > 0) + { + r_fx[0] = L_shl_pos(r_fx[0], 1); + } + ELSE + { + s = sub(s, 1); + } + + /* post-twiddle */ + FOR (i = 1; i <= lpc_order; i++) + { + r_fx[i] = L_add(Mpy_32_32_lc3plus(L_shl(x[2 * i], s), inv_odft_twiddle_re[i - 1]), + Mpy_32_32_lc3plus(L_shl(x[2 * i + 1], s), inv_odft_twiddle_im[i - 1])); move32(); + } + + *r_fx_exp = sub(d2_fx_exp, s); move16(); + + /* r_fx[0] must not be zero */ + IF (r_fx[0] == 0) + { + r_fx[0] = (Word32)0x7FFFFFFF; move32(); + FOR (i = 1; i <= lpc_order; i++) + { + r_fx[i] = 0; move32(); + } + *r_fx_exp = 0; move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/plc_tdc_lagwin_fx.c b/lib_lc3plus/plc_tdc_lagwin_fx.c new file mode 100644 index 000000000..e5bd94d66 --- /dev/null +++ b/lib_lc3plus/plc_tdc_lagwin_fx.c @@ -0,0 +1,32 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processLagwin_fx(Word32 r[], const Word32 w[], Word16 m) +{ + /* Start Processing */ + Counter i; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processLagwin_fx", sizeof(struct { Counter i; })); +#endif + + FOR (i = 0; i < m; i++) + { + r[i + 1] = Mpy_32_32_lc3plus(r[i + 1], w[i]); move32(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/plc_tdc_main_fx.c b/lib_lc3plus/plc_tdc_main_fx.c new file mode 100644 index 000000000..c6558dd1b --- /dev/null +++ b/lib_lc3plus/plc_tdc_main_fx.c @@ -0,0 +1,1257 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +/*****************************************************************************/ + +static Word16 TDC_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg); +static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg); +static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer, + const Word16 *hp_filt); +static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg); +static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc); +static void TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y); +static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg); +static void TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m); +static void TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const Word16 lg, const Word16 mem); +static void TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg, + const Word16 m); +static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg); + +#ifdef CR8_G_ADD_75MS +const Word16 beforeNextIncArray_fx[4][4] = {{0,0,0,1}, + {0,1,0,1}, + {0,1,1,1}, + {1,1,1,1}}; +const Word16 nextIncArray_fx[4][4] = {{1,0,0,0}, + {1,0,1,0}, + {1,0,1,1}, + {1,1,1,1}}; +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR +static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms); +static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest); +#endif + +/*****************************************************************************/ + + +/* + * processTimeDomainConcealment_Apply_fx + * + * Parameters: + * pitch_int i : integer pitch lag Q0 + * preemphFac_fx i : preemphase factor Q15 + * A_fx i : lp filter coefficients Qx + * pcmbufHist_fx i : pointer to input signal Qq_fx_old_exp + * frame_length i : frame length Q0 + * fs_idx i : sample rate index Q0 + * nbLostFramesInRow i : number of consecutive lost frames Q0 + * overlap i : overlap length Q0 + * stabFac_fx i : stability factor Q15 + * fract i/o: fraction of lag Q0 + * seed_fx i/o: pointer to seed Q0 + * gain_p_fx i/o: pointer to gainp Q15 + * gain_c_fx i/o: pointer to gainc 15Q16 + * synth_fx o : pointer to synthesized signal Q_syn + * Q_syn o : exponent for synthesized signal Q0 + * alpha o : damping factor Q15 + * scratchBuffer i : scratch buffer + * + * Function: + * Perform the time domain concealment. + * + * Returns: + * void + */ +void processTimeDomainConcealment_Apply_fx(const Word16 pitch_int, const Word16 preemphFac_fx, const Word16 *A_fx, + const Word16 lpc_order, const Word16 *pcmbufHist_fx, const Word16 frame_length, + const Word16 frame_dms, const Word16 fs_idx, const Word16 nbLostFramesInRow, + const Word16 overlap, const Word16 stabFac_fx, Word16 *fract, + Word16 *seed_fx, + Word32 *gain_c_fx, Word16 *synth_fx, Word16 *Q_syn, Word16 *alpha, Word16 max_len_pcm_plc, + Word16 harmonicBuf_fx[MAX_PITCH], Word16 synthHist_fx[M], Word16 *const harmonicBuf_Q, + Word8 *scratchBuffer +#ifdef CR9_I_INC_TDC_FADEOUT_LEN + ,UWord8 plc_fadeout_type +#endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + ,Word16 * alpha_type_2_table +#endif +) +{ + Counter i; + Word16 s, s1, c1, c2, len, cnt, g_fx, ilen, Tc, nextInc, beforeNextInc; + Word32 tmp32, tmp32_2, gainc_tmp; + Word16 gain_p_fx; + Word32 gain_c_32_fx; + Word16 gain_c_16_fx, gain_c_16_fx_exp, gain_inov_fx, gain_inov_fx_exp, ilen_exp; + Word16 hpBlendFac; + Word16 len_pi_lf_2, frame_length_2, step_fx, step_n_fx, gain_h_fx, nbLostCmpt_loc, mem_deemph; + Word16 * synth_mem_fx, *synth_tmp_fx, *exc2_fx, *exc_fx, *pt_exc, *pt1_exc, *x_pre_fx; + Word16 * harmonicBufPtr; + Word16 Q_exc = 0, exp_scale; + const Word16 *hp_filt_fx, *TDC_high_harm; + Word16 alphaPrev_fx; + Word16 throttle; +#ifdef CR8_G_ADD_75MS + Word16 frame_dms_idx, nbLostFramesInRow_mod; +#endif + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processTimeDomainConcealment_Apply_fx", sizeof(struct { + Counter i; + Word16 s, s1, c1, c2, len, cnt, g_fx, ilen, Tc, nextInc, beforeNextInc; + Word32 tmp32, tmp32_2, gainc_tmp; + Word16 gain_p_fx; + Word32 gain_c_32_fx; + Word16 gain_c_16_fx, gain_c_16_fx_exp, gain_inov_fx, gain_inov_fx_exp, ilen_exp; + Word16 hpBlendFac; + Word16 len_pi_lf_2, frame_length_2, step_fx, step_n_fx, gain_h_fx, nbLostCmpt_loc, mem_deemph; + Word16 * synth_mem_fx, *synth_tmp_fx, *exc2_fx, *exc_fx, *pt_exc, *pt1_exc, *x_pre_fx; + Word16 * harmonicBufPtr; + Word16 Q_exc, exp_scale; + const Word16 *hp_filt_fx, *TDC_high_harm; + Word16 alphaPrev_fx; + Word16 throttle; + Word16 frame_dms_idx, nbLostFramesInRow_mod; + })); +#endif + +#ifdef CR9_I_INC_TDC_FADEOUT_LEN + Word32 plc_fadeout_len = 0; +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + if (plc_fadeout_type >= 1){ +#else + if (plc_fadeout_type == 1){ +#endif + plc_fadeout_len = PLC_FADEOUT_TYPE_1_IN_MS; + } + else{ + plc_fadeout_len = PLC_FADEOUT_IN_MS; + } +#endif + + /* len of output signal */ + len = add(frame_length, overlap); + +#ifdef CR8_G_ADD_75MS + nbLostFramesInRow_mod = sub(nbLostFramesInRow, 1) & 0x0003; + + frame_dms_idx = mult(frame_dms, 0x051F); + nbLostCmpt_loc = add(shr(L_mult0(frame_dms_idx, sub(nbLostFramesInRow, 1)), 2), 1); + frame_dms_idx = sub(frame_dms_idx, 1); + beforeNextInc = beforeNextIncArray_fx[frame_dms_idx][nbLostFramesInRow_mod]; move16(); + nextInc = nextIncArray_fx [frame_dms_idx][nbLostFramesInRow_mod]; move16(); +#else + nbLostCmpt_loc = nbLostFramesInRow; move16(); + nextInc = 1; move16(); + beforeNextInc = 1; move16(); + SWITCH (frame_dms) + { + case 25: + nbLostCmpt_loc = shr(add(nbLostFramesInRow, 3), 2); + nextInc = (nbLostFramesInRow & 0x0003) == 1; move16(); + beforeNextInc = (nbLostFramesInRow & 0x0003) == 0; move16(); + BREAK; + case 50: + nbLostCmpt_loc = shr(add(nbLostFramesInRow, 1), 1); + nextInc = (nbLostFramesInRow & 0x0001) == 1; move16(); + beforeNextInc = (nbLostFramesInRow & 0x0001) == 0; move16(); + BREAK; + } +#endif + +#ifdef CR9_I_INC_TDC_FADEOUT_LEN + IF (sub(nbLostCmpt_loc, plc_fadeout_len / 10) > 0) +#else + IF (sub(nbLostCmpt_loc, PLC_FADEOUT_IN_MS / 10) > 0) +#endif + { + gain_p_fx = 0; move16(); + *gain_c_fx = 0; move32(); + *Q_syn = 0; move16(); + *alpha = 0; move16(); + basop_memset(synth_fx, 0, len * sizeof(Word16)); +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + return; + } + + frame_length_2 = shr_pos(frame_length, 1); + + Tc = pitch_int; move16(); + if (sub(*fract, 0) > 0) + { + Tc = add(Tc, 1); + } + + len_pi_lf_2 = add(Tc, frame_length_2); + + /*---------------------------------------------------------------- + * Buffer Initialization + * + * exc_fx synth_mem_fx + * |--exc_buf_past--|--exc_buf_curr--|--syn_mem--|--x_pre--| + * |--exc2--| + * |--syn--| + * + *---------------------------------------------------------------*/ + + /* pointer inits */ + exc_fx = (Word16 *)scratchAlign(scratchBuffer, + sizeof(Word16) * len_pi_lf_2); /* MAX_PITCH+MAX_LEN/2 + MAX_LEN+MDCT_MEM_LEN_MAX */ + synth_mem_fx = (Word16 *)scratchAlign(exc_fx, sizeof(*exc_fx) * len); /* M */ + x_pre_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_PITCH+MAX_LEN/2+M+1 */ + exc2_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_LEN+MDCT_MEM_LEN_MAX+TDC_L_FIR_HP-1 */ + synth_tmp_fx = (Word16 *)scratchAlign(synth_mem_fx, sizeof(*synth_mem_fx) * lpc_order); /* MAX_LEN+MDCT_MEM_LEN_MAX */ + /* Buffers 'overlap' since they are not used at the same time */ + + /*---------------------------------------------------------------* + * LPC Residual * + *---------------------------------------------------------------*/ + IF (sub(nbLostFramesInRow, 1) == 0) + { + + /* copy buffer to pre-emphasis buffer */ + cnt = add(len_pi_lf_2, lpc_order + 1); + basop_memmove(&x_pre_fx[0], &pcmbufHist_fx[max_len_pcm_plc - cnt], cnt * sizeof(Word16)); + + /* apply pre-emphasis to the signal; x_pre = x_pre_flt * 2^(q_fx_old_exp-15-Q_exc+1) */ + Q_exc = TDC_preemph(&(x_pre_fx[1]), preemphFac_fx, sub(cnt, 1)); + + /* copy memory for LPC synth */ + basop_memmove(&synth_mem_fx[0], &x_pre_fx[len_pi_lf_2 + 1], lpc_order * sizeof(Word16)); + + /* LPC Residual; exc = exc_fx * 2^(q_fx_old_exp-15-Q_exc) */ + TDC_LPC_residu_fx(A_fx, &(x_pre_fx[lpc_order + 1]), &(exc_fx[-len_pi_lf_2]), len_pi_lf_2, lpc_order); + } + + /*---------------------------------------------------------------* + * Calculate gains * + *---------------------------------------------------------------*/ + + IF (sub(nbLostFramesInRow, 1) == 0) + { + IF (sub(pitch_int, Tc) == 0) + { + gain_p_fx = + round_fx_sat(L_shl_sat(TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 1]), frame_length_2), 15)); + } + ELSE + { + tmp32 = TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 2]), frame_length_2); + tmp32_2 = TDC_calcGainp(&(x_pre_fx[lpc_order + Tc + 1]), &(x_pre_fx[lpc_order + 1]), frame_length_2); + + IF (L_sub(tmp32, tmp32_2) > 0) + { + Tc = pitch_int; move16(); + gain_p_fx = round_fx_sat(L_shl_sat(tmp32, 15)); + *fract = 0; move16(); + } + ELSE + { + gain_p_fx = round_fx_sat(L_shl_sat(tmp32_2, 15)); + } + } + + if (gain_p_fx < 0) + { + gain_p_fx = 0; move16(); + } + + IF (sub(pitch_int, Tc) == 0) + { + /* gain_c = gain_c_32_fx * 2^(q_fx_old_exp-31) */ + TDC_calcGainc(exc_fx, Q_exc, Tc, frame_length_2, frame_dms, gain_p_fx, &gain_c_32_fx); + } + ELSE + { + TDC_calcGainc(exc_fx, Q_exc, pitch_int, frame_length_2, frame_dms, gain_p_fx, &tmp32); + TDC_calcGainc(exc_fx, Q_exc, Tc , frame_length_2, frame_dms, gain_p_fx, &gain_c_32_fx); + + gain_c_32_fx = L_min(gain_c_32_fx, tmp32); move32(); + } + } + ELSE + { + gain_c_32_fx = *gain_c_fx; move32(); + gain_p_fx = *alpha; + } + + /*---------------------------------------------------------------* + * Damping factor * + *---------------------------------------------------------------*/ + + alphaPrev_fx = 0x7FFF; move16(); + IF (sub(nbLostFramesInRow,1) > 0) + { + alphaPrev_fx = *alpha; move16(); + } +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + IF (sub(plc_fadeout_type,2) == 0 ){ +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + *alpha = alpha_type_2_table[nbLostFramesInRow]; +#else + IF (sub(frame_dms,50) == 0){ + IF (sub(nbLostFramesInRow,30) >= 0){ + *alpha = 0; move16(); + } ELSE { + *alpha = FADE_OUT_TYPE_2_ALPHA_5MS[nbLostFramesInRow]; move16(); + } + } + IF (sub(frame_dms,25) == 0){ + IF (sub(nbLostFramesInRow,60) >= 0){ + *alpha = 0; move16(); + } ELSE { + *alpha = FADE_OUT_TYPE_2_ALPHA_2_5MS[nbLostFramesInRow]; move16(); + } + } +#endif + } + ELSE{ +#endif + IF (nextInc != 0) + { + IF (sub(nbLostCmpt_loc, 1) == 0) + { + /* Threshold 31470 is 0.98^2 in Q15 format */ + IF (sub(gain_p_fx, 31470) > 0) + { + *alpha = 0x7D71; /*0.98f*/ + move16(); + } + /* Threshold 28037 is 0.925^2 in Q15 format */ + ELSE IF (sub(gain_p_fx, 28037) < 0) + { + *alpha = 0x7666; /*0.925f*/ + move16(); + } + ELSE + { + exp_scale = 0; + *alpha = Sqrt16_lc3plus(gain_p_fx, &exp_scale); move16(); + *alpha = shl(*alpha, exp_scale); + } + } + ELSE + { + SWITCH (nbLostCmpt_loc) + { + case 2: + c1 = 0x50A4; /*0.630f*/ + move16(); + c2 = 0x2CCD; /*0.350f*/ + move16(); + BREAK; + default: + c1 = 0x5375; /*0.652f*/ + move16(); + c2 = 0x29FC; /*0.328f*/ + move16(); + BREAK; + } + + *alpha = mult_r(stabFac_fx, c2); + *alpha = add(*alpha, c1); + + *alpha = mult(gain_p_fx, *alpha); + + + IF (sub(nbLostCmpt_loc, 2) == 0) + { + if (sub(*alpha, 0x75A2 /*0.919f*/) < 0) + { + *alpha = 0x75A2; move16(); + } + } + ELSE IF (sub(nbLostCmpt_loc, 5) > 0) + { + gain_p_fx = *alpha; move16(); + } + } + } + + IF (sub(nbLostCmpt_loc,3) > 0) + { + SWITCH (frame_dms) + { + case 25: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK; +#ifdef CR9_J_SLOW_TDC_FADEOUT + case 50: *alpha = mult(*alpha, PLC34_ATTEN_FAC_025_FX); BREAK; +#else + case 50: *alpha = mult(*alpha, PLC34_ATTEN_FAC_050_FX); BREAK; +#endif +#ifdef CR8_G_ADD_75MS + case 75: *alpha = mult(*alpha, PLC34_ATTEN_FAC_075_FX); BREAK; +#endif + case 100: *alpha = mult(*alpha, PLC34_ATTEN_FAC_100_FX); BREAK; + } + } + if (sub(nbLostCmpt_loc, 5) > 0) + { + gain_p_fx = *alpha; move16(); + } +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + } +#endif + + /*---------------------------------------------------------------* + * Construct the harmonic part * + * Last pitch cycle of the previous frame is repeatedly copied. * + *---------------------------------------------------------------*/ + + pt_exc = harmonicBuf_fx; move16(); + pt1_exc = exc_fx - Tc; move16(); + s = s_min(len, Tc); move16(); + test(); + IF (sub(nbLostFramesInRow, 1) == 0) + { + *harmonicBuf_Q = Q_exc; move16(); + IF (sub(stabFac_fx, 32767 /*1.f Q15*/) >= 0) + { + basop_memmove(pt_exc, pt1_exc, Tc * sizeof(Word16)); + } + ELSE + { + /* These values are necessary for the last five filtered samples */ + basop_memmove(exc_fx, &exc_fx[-Tc], (TDC_L_FIR_HP-1)/2 * sizeof(Word16)); + TDC_high_harm = TDC_high_32_harm; + if (sub(fs_idx, 1) <= 0) + { + TDC_high_harm = TDC_high_16_harm; + } + FOR (i = 0; i < Tc; i++) + { + pt_exc[i] = TDC_Dot_product(&pt1_exc[i-(TDC_L_FIR_HP-1)/2], TDC_high_harm, TDC_L_FIR_HP); + } + } + } + ELSE + { + Q_exc = *harmonicBuf_Q; move16(); + } + + + /*---------------------------------------------------------------* + * Construct the random part of excitation * + *---------------------------------------------------------------*/ + + TDC_random_fx(seed_fx, add(len, sub(TDC_L_FIR_HP, 1)), exc2_fx); + + /* high pass noise */ + hp_filt_fx = TDC_high_32; + if (sub(fs_idx, 1) <= 0) + { + hp_filt_fx = TDC_high_16; + } + + IF (sub(nbLostFramesInRow, 1) == 0) + { + TDC_highPassFiltering_fx(len, exc2_fx, TDC_L_FIR_HP, hp_filt_fx); + } + ELSE + { + throttle = div_s(nbLostCmpt_loc, add(nbLostCmpt_loc, PLC3_HPBLENDTHROTTLE)); + hpBlendFac = mult(sub(0x7FFF, *alpha), throttle); + c1 = sub(0x7FFF, hpBlendFac); + FOR (i = 0; i < len; i++) + { + /* Return value of dot product is Q1 */ + tmp32 = Mpy_32_16_lc3plus(TDC_L_Dot_product(&exc2_fx[i], hp_filt_fx, TDC_L_FIR_HP), c1 /*Q15*/); + exc2_fx[i] = round_fx(L_mac0(tmp32, hpBlendFac, exc2_fx[i+TDC_L_FIR_HP/2])); move16(); + } + } + + /* normalize energy */ + TDC_normalize_energy_fx(&gain_inov_fx, &gain_inov_fx_exp, exc2_fx, frame_length); + tmp32 = Mpy_32_16_lc3plus( + L_sub(590558016l /*1.1 Q29*/, Mpy_32_16_lc3plus(L_shr_pos(L_deposit_h(gain_p_fx), 2), 24576 /*0.75*/)) /*Q29*/, + gain_inov_fx /*Q15,gain_inov_e*/); /*Q29,gain_inov_e*/ + s = norm_l(tmp32); + tmp32 = L_shl_pos(tmp32, s); + tmp32 = L_min(tmp32, 0x7FFEFFFF); + gain_inov_fx_exp = add(sub(gain_inov_fx_exp, s), 31 - 29); /*->Q31*/ + gain_inov_fx = round_fx(tmp32); /*Q15,gain_inov_e*/ + + /* gains */ + gain_h_fx = alphaPrev_fx; move16(); + + /* update steps */ + if (frame_length == 720) + { + ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, 960, &ilen_exp); + } else { + ilen = BASOP_Util_Divide1616_Scale_lc3plus((Word16)1, frame_length, &ilen_exp); + } + step_fx = round_fx(L_shl(L_mult(sub(gain_h_fx, *alpha), ilen), ilen_exp)); + + s = norm_l(gain_c_32_fx); + tmp32 = L_shl_pos(gain_c_32_fx, s); + + gain_c_16_fx = extract_h(tmp32); + gain_c_16_fx_exp = sub(15, s); +#ifdef CR9_M_FIX_DIV_ZERO + gainc_tmp = L_mult (gain_c_16_fx, div_s(*alpha, s_max(alphaPrev_fx, 1))); +#else + gainc_tmp = L_mult (gain_c_16_fx, div_s(*alpha, alphaPrev_fx)); +#endif + tmp32 = L_sub (tmp32, gainc_tmp); + step_n_fx = round_fx(L_shl(Mpy_32_16_lc3plus(tmp32, ilen), ilen_exp)); + + /*---------------------------------------------------------------* + * Construct the total excitation * + *---------------------------------------------------------------*/ + + harmonicBufPtr = harmonicBuf_fx + ((nbLostFramesInRow - 1) * frame_length) % Tc; + + s1 = add(Q_exc, add(gain_inov_fx_exp, gain_c_16_fx_exp)); + cnt = add(frame_length, TDC_L_FIR_HP / 2); + + g_fx = mult_r(gain_c_16_fx, gain_inov_fx); + + FOR (i = 0; i < len; i++) + { + /* harmonic */ + if (harmonicBufPtr - harmonicBuf_fx >= Tc) { + harmonicBufPtr = harmonicBuf_fx; + } + exc_fx[i] = *harmonicBufPtr++; + tmp32 = L_mult(exc_fx[i], gain_h_fx); + /* random */ + tmp32_2 = L_shl_sat(L_mult(exc2_fx[i], g_fx), s1); + /* total */ + exc_fx[i] = round_fx_sat(L_add_sat(tmp32, tmp32_2)); move16(); + /* update */ + gain_h_fx = s_max(sub(gain_h_fx, step_fx), 0); + gain_c_16_fx = s_max(sub(gain_c_16_fx, step_n_fx), 0); + g_fx = mult_r(gain_c_16_fx, gain_inov_fx); + } + + /* update gain */ + *gain_c_fx = L_shl(gainc_tmp, sub(gain_c_16_fx_exp, 15)); move32(); + + + /*----------------------------------------------------------* + * Compute the synthesis speech * + *----------------------------------------------------------*/ + + /* introduce some headroom to avoid Overflows, 2 bit seem to be sufficient */ + *Q_syn = sub(Q_exc, 2); + *Q_syn = s_max(*Q_syn, -3); + + exp_scale = sub(*Q_syn, Q_exc - 1); + + IF (sub(nbLostFramesInRow, 1) != 0) + { + synth_mem_fx = synthHist_fx; + } + Copy_Scale_sig(synth_mem_fx, &synth_tmp_fx[-lpc_order], lpc_order, exp_scale); + TDC_LPC_synthesis_fx(sub(Q_exc, *Q_syn), A_fx, exc_fx, synth_tmp_fx, len, lpc_order); + + FOR (i=0; i= 0); + synth_fx[i] = mult(synth_fx[i], gain_h_fx); + gain_h_fx = sub(gain_h_fx, step_fx); + } + basop_memset(&synth_fx[frame_length], 0, overlap * sizeof(Word16)); + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + +/*****************************************************************************/ + +static Word32 syn_kern_2(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = L_msu_sat(L_tmp, y[-1], a[1]); + L_tmp = L_msu_sat(L_tmp, y[-2], a[2]); + return L_tmp; +} + +static Word32 syn_kern_4(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_2(L_tmp, a, y); + return syn_kern_2(L_tmp, a + 2, y - 2); +} + +static Word32 syn_kern_8(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_4(L_tmp, a, y); + return syn_kern_4(L_tmp, a + 4, y - 4); +} + +static Word32 syn_kern_16(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_8(L_tmp, a, y); + return syn_kern_8(L_tmp, a + 8, y - 8); +} + +/* + * TDC_Dot_product + * + * Parameters: + * x i: x vector Q0 + * y i: y vector Q0 + * lg i: vector length Q0 + * + * Function: + * dot product + * + * Returns: + * dot product Q0 + */ +static Word16 TDC_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word32 sum; + ); + + sum = L_mult(x[0], y[0]); + FOR (i = 1; i < lg-1; i++) + { + sum = L_mac_sat(sum, x[i], y[i]); + } + + sum = mac_r_sat(sum, x[lg-1], y[lg-1]); + + Dyn_Mem_Deluxe_Out(); + + return sum; +} + +/* + * TDC_L_Dot_product + * + * Parameters: + * x i: x vector Q0 + * y i: y vector Q0 + * lg i: vector length Q0 + * + * Function: + * dot product + * + * Returns: + * dot product Q1 + */ +static Word32 TDC_L_Dot_product(const Word16 x[], const Word16 y[], const Word16 lg) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word32 sum; + ); + + sum = L_mac0(1L, x[0], y[0]); + FOR (i = 1; i < lg; i++) + { + sum = L_mac0(sum, x[i], y[i]); + } + + Dyn_Mem_Deluxe_Out(); + + return sum; +} + +/* + * TDC_highPassFiltering_fx + * + * Parameters: + * L_buffer i: buffer length + * exc2 i: unvoiced excitation before the high pass filtering Qx/Qx+1 + * l_fir_fer i: length highpass filter + * hp_filt i: highpass filter coefficients Q15 + * + * Function: + * Highpass filter + * + * Returns: + * void + */ +static void TDC_highPassFiltering_fx(const Word16 L_buffer, Word16 exc2[], const Word16 l_fir_fer, + const Word16 *hp_filt) +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + + FOR (i = 0; i < L_buffer; i++) + { + exc2[i] = round_fx(L_sub(TDC_L_Dot_product(&exc2[i], hp_filt, l_fir_fer), 1)); move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +/* + * TDC_calcGainc + * + * Parameters: + * exc i: pointer to excitation buffer + * Q_exc i: Q format of excitation buffer + * old_fpitch i: pitch_int + * lg i: length + * lp_gainp i: gain p + * lp_gainc o: pointer to gain (15Q16) + * + * Function: + * Gain calculation + * + * Returns: + * void + */ +static void TDC_calcGainc(Word16 *exc, Word16 Q_exc, Word16 old_fpitch, Word16 lg, Word16 frame_dms, Word16 lp_gainp, Word32 *lp_gainc) +{ + Dyn_Mem_Deluxe_In( + Word16 tmp16, tmp_e, tmp2_e; + Word32 L_tmp, L_tmp_max; + Counter i; + ); + + L_tmp = L_deposit_l(0); + + FOR (i = 0; i < lg; i++) + { + /* gain_c += ( exc[-i-1] - *gain_p * exc[-i-1-pitch_int] ) * ( exc[-i-1] - *gain_p * exc[-i-1-pitch_int] ); */ + tmp16 = sub_sat(exc[i - lg] /*Q1*/, mult_r(lp_gainp /*Q15*/, exc[i - lg - old_fpitch] /*Q1*/) /*Q1*/); + L_tmp = L_mac0_sat(L_tmp, tmp16, tmp16); /*Q3*/ + } + + IF (sub(frame_dms, 100) < 0) + { + L_tmp_max = L_deposit_l(0); + FOR (i = 0; i < lg; i++) + { + L_tmp_max = L_mac0_sat(L_tmp_max, exc[i - lg], exc[i - lg]); /*Q3*/ + } + L_tmp = L_min(L_tmp, L_tmp_max); + } + + tmp_e = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, tmp_e); + tmp_e = sub(sub(31, shl_pos(Q_exc, 1)), tmp_e); /*L_tmp is Q31, now*/ + tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(L_tmp /*Q31,norm,tmp_e*/, lg /*Q15,15*/, &tmp2_e) /*Q15,tmp2_e+tmp_e-15*/; + tmp_e = sub(add(tmp2_e, tmp_e), 15); + + IF (tmp16 != 0) + { + tmp16 = Sqrt16_lc3plus(tmp16, &tmp_e); /*Q15,norm,tmp_e*/ + tmp_e = L_min(tmp_e, 15); + *lp_gainc = L_shl_pos(L_deposit_l(tmp16), add(tmp_e, 1)); /*15Q16*/ + move32(); + } + ELSE + { + *lp_gainc = 0; + } + + Dyn_Mem_Deluxe_Out(); +} + +/* + * TDC_calcGainp + * + * Parameters: + * x i: input signal + * y i: shifted input signal + * lg i: vector length + * + * Function: + * Gain calculation + * + * Returns: + * gain (15Q16) + */ +static Word32 TDC_calcGainp(Word16 x[], Word16 y[], Word16 lg) +{ + Dyn_Mem_Deluxe_In( + Word32 tcorr, tener, Lgain, L_tmp1, L_tmp2; + Word16 m_corr, m_ener, negative, Q_corr, Q_ener; + Counter i; + ); + + negative = 0; move16(); + + L_tmp1 = L_deposit_l(0); + L_tmp2 = L_deposit_l(0); + FOR (i = 0; i < lg; i += 2) + { + L_tmp1 = L_mac0_sat(L_tmp1, x[i], y[i]); + L_tmp2 = L_mac0_sat(L_tmp2, x[i + 1], y[i + 1]); + } + tcorr = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1)); + Q_corr = norm_l(tcorr); + tcorr = L_shl(tcorr, Q_corr); + Q_corr = sub(2, Q_corr); + + L_tmp1 = L_deposit_l(0); + L_tmp2 = L_deposit_l(0); + FOR (i = 0; i < lg; i += 2) + { + L_tmp1 = L_mac0_sat(L_tmp1, y[i], y[i]); + L_tmp2 = L_mac0_sat(L_tmp2, y[i + 1], y[i + 1]); + } + tener = L_add(L_shr_pos(L_tmp1, 1), L_shr_pos(L_tmp2, 1)); + Q_ener = norm_l(tener); + tener = L_shl(tener, Q_ener); + Q_ener = sub(2, Q_ener); + + tener = L_max(tener, 1); + + if (tcorr <= 0) + { + negative = 1; move16(); + } + tcorr = L_abs(tcorr); + + m_corr = extract_h(tcorr); + + m_ener = extract_h(tener); + + IF (sub(m_corr, m_ener) > 0) + { + m_corr = shr_pos(m_corr, 1); + Q_corr = add(Q_corr, 1); + } + if (m_ener == 0) + { + move16(); + m_corr = 0x7FFF; + } + if (m_ener != 0) + { + m_corr = div_s(m_corr, m_ener); + } + + Q_corr = sub(Q_corr, Q_ener); + + Lgain = L_shl(L_deposit_l(m_corr), add(Q_corr, 1)); + + if (negative != 0) + { + Lgain = L_negate(Lgain); + } + + Dyn_Mem_Deluxe_Out(); + + return Lgain; +} + +/* + * TDC_LPC_synthesis_fx + * + * Parameters: + * sh i : scaling to apply for a[0] Q0 + * a[] i : LP filter coefficients Qx + * x[] i : input signal Qx + * y[] o : output signal Qx-s + * lg i : size of filtering Q0 + * m i : order of LP filter Q0 + * + * Function: + * Apply LP filtering to obtain synthesis signal. + * Memory size is always m. + * + * Returns: + * void + */ +static void TDC_LPC_synthesis_fx(const Word16 sh, const Word16 a[], const Word16 x[], Word16 y[], const Word16 lg, + const Word16 m) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word16 a0; + Word16 q; + Word32(*syn_kern)(Word32 L_tmp, const Word16 a[], const Word16 y[] + );); + + ASSERT(m == 16 || m == 8); + + if (sub(m, 16) == 0) + { + syn_kern = syn_kern_16; + } + if (sub(m, 8) == 0) + { + syn_kern = syn_kern_8; + } + + q = add(norm_s(a[0]), 1); + a0 = shr_sat(a[0], sh); + + FOR (i = 0; i < lg; i++) + { + y[i] = round_fx_sat(L_shl_sat(syn_kern(L_mult(a0, x[i]), a, &y[i]), q)); move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +/* TDC_LPC_residu_fx + * + * Parameters: + * a I: LP filter coefficients (Qx) + * x I: input signal + * y O: output signal + * lg I: size of filtering + * m I: lpc order + * + * Function: + * Apply inverse filtering to obtain LP residual signal. + * + * Returns: + * void + */ +static void TDC_LPC_residu_fx(const Word16 *a, Word16 *x, Word16 *y, Word16 lg, Word16 m) +{ + Dyn_Mem_Deluxe_In( + Word16 a_exp; + Word32 s; + Counter i; + ); + + ASSERT(m == 16 || m == 8); + + a_exp = add(norm_s(a[0]), 1); + a_exp = add(a_exp, 1); + + IF (sub(m, 16) == 0) + { + FOR (i = 0; i < lg; i++) + { + s = L_mult(x[i], a[0]); + s = L_mac_sat(s, x[i - 1], a[1]); + s = L_mac_sat(s, x[i - 2], a[2]); + s = L_mac_sat(s, x[i - 3], a[3]); + s = L_mac_sat(s, x[i - 4], a[4]); + s = L_mac_sat(s, x[i - 5], a[5]); + s = L_mac_sat(s, x[i - 6], a[6]); + s = L_mac_sat(s, x[i - 7], a[7]); + s = L_mac_sat(s, x[i - 8], a[8]); + s = L_mac_sat(s, x[i - 9], a[9]); + s = L_mac_sat(s, x[i - 10], a[10]); + s = L_mac_sat(s, x[i - 11], a[11]); + s = L_mac_sat(s, x[i - 12], a[12]); + s = L_mac_sat(s, x[i - 13], a[13]); + s = L_mac_sat(s, x[i - 14], a[14]); + s = L_mac_sat(s, x[i - 15], a[15]); + s = L_mac_sat(s, x[i - 16], a[16]); + + s = L_shl_sat(s, a_exp); + y[i] = round_fx_sat(s); move16(); + } + } + IF (sub(m, 8) == 0) + { + FOR (i = 0; i < lg; i++) + { + s = L_mult(x[i], a[0]); + s = L_mac_sat(s, x[i - 1], a[1]); + s = L_mac_sat(s, x[i - 2], a[2]); + s = L_mac_sat(s, x[i - 3], a[3]); + s = L_mac_sat(s, x[i - 4], a[4]); + s = L_mac_sat(s, x[i - 5], a[5]); + s = L_mac_sat(s, x[i - 6], a[6]); + s = L_mac_sat(s, x[i - 7], a[7]); + s = L_mac_sat(s, x[i - 8], a[8]); + + s = L_shl_sat(s, a_exp); + y[i] = round_fx_sat(s); move16(); + } + } + + Dyn_Mem_Deluxe_Out(); +} + +/* TDC_random_fx + * + * Parameters: + * seed i/o: seed for random number + * lg i : vector length + * y o : output values + * + * Function: + * Uniform distributed random generator. + * + * Returns: + * random number + */ +static void TDC_random_fx(Word16 *seed, Word16 lg, Word16 *y) +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + + FOR (i = 0; i < lg; i++) + { + *seed = extract_l(L_mac0(16831L, *seed, 12821)); + *y++ = *seed; move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +/* + * TDC_preemph + * + * Parameters: + * x i/o: signal Qx + * fac i: preemphasis factor Q15 + * lg i: vector length + * + * Function: + * Filtering through 1 - fac z^-1 + * + * Returns: + * Q-factor + */ +static Word16 TDC_preemph(Word16 *x, const Word16 fac, const Word16 lg) +{ + Dyn_Mem_Deluxe_In( + Word16 fac_sh, Q_max_value, Q_out; + Word32 max_val; + Counter i; + ); + + fac_sh = shr(fac, 3); + Q_max_value = 4096; move16(); + Q_out = 12; move16(); + + max_val = 0; move32(); + FOR (i = sub(lg, 1); i >= 0; i--) + { + max_val = L_max(L_abs(L_msu(L_mult(x[i], Q_max_value), x[i - 1], fac_sh)), max_val); + } + + IF (extract_h(max_val) != 0) + { + Q_out = s_min(s_max(sub(norm_s(extract_h(max_val)), 3), 0), 12); + } + + FOR (i = sub(lg, 1); i >= 0; i--) + { + x[i] = round_fx(L_shl(L_msu(L_mult(x[i], Q_max_value), x[i - 1], fac_sh), Q_out)); move16(); + } + + Dyn_Mem_Deluxe_Out(); + + return sub(Q_out, 2); +} + +/* + * TDC_deemph_fx + * + * Parameters: + * x i: input signal Qx + * y o: output signal Qx + * fac i: deemphasis factor Q15 + * lg i: size of filtering Q0 + * mem i: memory (x[-1]) + * + * Function: + * Filtering through 1/(1-fac z^-1) + * + * Returns: + * void + */ +static void TDC_deemph_fx(const Word16 *x, Word16 *y, const Word16 fac, const Word16 lg, const Word16 mem) +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + + y[0] = round_fx_sat(L_mac_sat(L_deposit_h(x[0]), mem, fac)); move16(); + FOR (i = 1; i < lg; i++) + { + y[i] = round_fx_sat(L_mac_sat(L_deposit_h(x[i]), y[i - 1], fac)); move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +/* + * TDC_normalize_energy_fx + * + * Parameters: + * gain o: gain + * gain_exp o: exponent of gain + * x i: input signal + * lg i: length of input signal + * + * Function: + * Normalizes the energy. + * + * Returns: + * void + */ +static void TDC_normalize_energy_fx(Word16 *gain, Word16 *gain_exp, const Word16 *x, const Word16 lg) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word16 c; + Word16 e; + Word16 e1; + Word16 e2; + Word32 tmp; + Word16 tmp16; + ); + + tmp = 0; move32(); + FOR (i = 0; i < lg; i++) + { + tmp16 = mult_r(x[i], 2048); + tmp = L_mac(tmp, tmp16, tmp16); + } + + e = norm_l(tmp); + tmp = L_shl_pos(tmp, e); + e1 = sub(sub(30, e), -8); move16(); + tmp16 = BASOP_Util_Divide3216_Scale_lc3plus(tmp, lg, &e2); + + e = 0; move16(); + if (tmp16 != 0) + { + e = sub(add(e1, e2), 15); + } + + c = 0x0148; /* 0.01 */ + move16(); + IF (e > 0) + { + c = shr(c, s_min(e, 15)); + } + ELSE + { + tmp16 = shr(tmp16, s_min(negate(e), 15)); + e = 0; move16(); + } + + e2 = 2; move16(); + if (s_and(e, 1)) + { + e2 = 1; move16(); + } + + tmp16 = add(shr_pos(tmp16, e2), shr_pos(c, e2)); + e = add(e, e2); + + tmp16 = Sqrt16_lc3plus(tmp16, &e); + + *gain = BASOP_Util_Divide1616_Scale_lc3plus((Word16)0x7FFF, tmp16, &e1); move16(); + *gain_exp = sub(e1, e); move16(); + + Dyn_Mem_Deluxe_Out(); +} + +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR +static Word16 type_2_alpha_long(Word16 nbLostFramesInRow, Word16 frame_dms) +{ + Word16 n_help; + Word32 n_shift; + + if (nbLostFramesInRow <= 3*(100.0/frame_dms)){ + n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms; + return powWord16rest(31129,n_help/100,n_help%100); + } + else { + n_shift = (nbLostFramesInRow - 3*(100/frame_dms)) * 50/frame_dms; + n_help = (n_shift + (100/frame_dms) - 1) * frame_dms; + return powWord16rest(22937,n_help/100,n_help%100); + } +} + +Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms) +{ + Word16 n_help; + Word16 selector = PLC_FADEOUT_TYPE_2_SELECTOR * 2 * (100/frame_dms); + + if (selector >= nbLostFramesInRow){ + return type_2_alpha_long(nbLostFramesInRow, frame_dms); + } + else { + n_help = (nbLostFramesInRow + (100/frame_dms) - 1) * frame_dms; + return powWord16rest(16383,n_help/100, n_help%100); + } +} + +static Word16 powWord16rest(Word16 base, Word16 exp, Word16 rest) { + Word32 exp_result = 32767; + Word32 tmp_result; + Word16 root, i, exp2; + + FOR (i = 0; i < exp; ++i) { + tmp_result = (Word32)exp_result * base; + exp_result = (Word16)(tmp_result >> 15); + } + + IF (rest != 0) { + exp2 = 0; + SWITCH (rest) + { + case 50: + root = Sqrt16_lc3plus(base, &exp2); + shr(root,exp2); + exp_result = L_shr(exp_result * root,15); /* 0.5^1.5 = 0.5^(3/2) = 0.5^3*sqrt(0.5) */ + BREAK; + case 25: + root = Sqrt16_lc3plus(base, &exp2); + shr(root,exp2); + exp2 = 0; + root = Sqrt16_lc3plus(root, &exp2); + shr(root,exp2); + exp_result = L_shr(exp_result * root,15); /* 0.5^(1/4) = 0.5^sqrt(sqrt(0.5)) */ + BREAK; + case 75: + root = Sqrt16_lc3plus(base, &exp2); + shr(root,exp2); + exp2 = 0; + root = Sqrt16_lc3plus(root, &exp2); + shr(root,exp2); + tmp_result = powWord16rest(root, 3, 0); + exp_result = L_shr( exp_result * tmp_result,15); + BREAK; + } + } + return (Word16) exp_result; +} +#endif diff --git a/lib_lc3plus/plc_tdc_pre_emphasis_fx.c b/lib_lc3plus/plc_tdc_pre_emphasis_fx.c new file mode 100644 index 000000000..3a961acf7 --- /dev/null +++ b/lib_lc3plus/plc_tdc_pre_emphasis_fx.c @@ -0,0 +1,95 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processPreEmphasis_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 frame_dms, Word8 *scratchBuffer) +{ + Word16 s; + Word32 nrg; + Word16 smax; + Counter band; + const Word16 *pre_emph; + const Word16 *pre_emph_e; + Word16 * d2_band_fx_exp; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processPreEmphasis_fx", sizeof(struct { + Word16 s; + Word32 nrg; + Word16 smax; + Counter band; + const Word16 *pre_emph; + const Word16 *pre_emph_e; + Word16 * d2_band_fx_exp; + })); +#endif + + d2_band_fx_exp = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_BANDS_NUMBER_PLC = 160 bytes */ + + pre_emph = lpc_lin_pre_emphasis[fs_idx]; + pre_emph_e = lpc_lin_pre_emphasis_e[fs_idx]; + SWITCH (frame_dms) + { + case 25: + pre_emph = lpc_lin_pre_emphasis_2_5ms[fs_idx]; + pre_emph_e = lpc_lin_pre_emphasis_e_2_5ms[fs_idx]; + BREAK; + case 50: + pre_emph = lpc_lin_pre_emphasis_5ms[fs_idx]; + pre_emph_e = lpc_lin_pre_emphasis_e_5ms[fs_idx]; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + pre_emph = lpc_lin_pre_emphasis_7_5ms[fs_idx]; + pre_emph_e = lpc_lin_pre_emphasis_e_7_5ms[fs_idx]; + BREAK; +#endif + } + + ASSERT(n_bands==20 || n_bands==40 || n_bands==60 || n_bands ==80); + + /* start processing */ + smax = -31; move16(); + + FOR (band = 0; band < n_bands; band++) + { + nrg = Mpy_32_16_lc3plus(d2_fx[band], pre_emph[band]); + + if (nrg == 0) + { + s = 31; move16(); + } + + if (nrg != 0) + { + s = norm_l(nrg); + } + + d2_fx[band] = L_shl_pos(nrg, s); move32(); + d2_band_fx_exp[band] = sub(pre_emph_e[band], s); move16(); + + smax = s_max(smax, d2_band_fx_exp[band]); + } + +/* Rescale band energies */ + FOR (band = 0; band < n_bands; band++) + { + d2_fx[band] = L_shr_pos(d2_fx[band], s_min(sub(smax, d2_band_fx_exp[band]), 31)); move32(); + } + /* Save common exponent for all bands */ + *d2_fx_exp = add(*d2_fx_exp, smax); move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/plc_update_aft_imdct_fx.c b/lib_lc3plus/plc_update_aft_imdct_fx.c new file mode 100644 index 000000000..663f491c9 --- /dev/null +++ b/lib_lc3plus/plc_update_aft_imdct_fx.c @@ -0,0 +1,343 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +static void processPLCcomputeStabFac(Word16 scf_q[], Word16 old_scf_q[], Word16 prev_bfi, Word16 *stab_fac); + +void processPLCUpdateAfterIMDCT_fx(Word16 x_fx[], Word16 q_fx_exp, Word16 concealMethod, Word16 xLen, Word16 fs_idx, + Word16 *nbLostFramesInRow, Word16 *prev_prev_bfi, Word16 *prev_bfi, Word16 bfi, Word16 scf_q[], + Word16 *ns_cum_alpha, AplcSetup *plcAd) +{ + Word16 oldLen, usedHistlen; + Word16 scale_fac_old, scale_fac_new, q_theo_new_old, q_theo_new_new, q_new, shift_old, shift_new; + Word16 frontLen, pastLen; + Word16 marginOldPast; + Word16 marginNewXlen, marginOldFront; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processPLCUpdateAfterIMDCT_fx", sizeof(struct { + Word16 oldLen, usedHistlen; + Counter i; + Word16 scale_fac_old, scale_fac_new, q_theo_new_old, q_theo_new_new, q_new, shift_old, shift_new; + Word16 frontLen, pastLen; + Word16 marginOldPast; + Word16 scale_fac_old_dual; + Word16 marginNewXlen, marginOldFront; + })); +#endif + + + + +#ifdef WMOPS + BASOP_sub_sub_start("processPLCUpdateAfterIMDCT "); +#endif + + + if (plcAd) + { + /* for short NB frames(2.5 ms) TDC-filtering requires more PCM samples than the plc_xcorr function */ + usedHistlen = plcAd->max_len_pcm_plc; + + + logic16(); + IF( (sub(bfi,1) == 0) && sub(concealMethod, LC3_CON_TEC_PHASE_ECU) == 0 && xLen == (Word16)(((double)LprotSzPtr[fs_idx])*0.625)) + { /* % reduced buffering update length during concealment method 2 as Xsav_fx is stored in the joint q_old_fx and pcmbufHist buffer */ + usedHistlen = sub(usedHistlen, sub(LprotSzPtr[fs_idx], s_min(MAX_BW_BIN, xLen))); + ASSERT(xLen == (Word16)(((double)LprotSzPtr[fs_idx])*0.625)); /*/ only enter here for 10 ms cases */ + + /* actually one can select to always update xLen(10 ms) less samples of x_old_tot, also in TDC-PLC bfi frames ,, and for PhECU.PLC */ + } + oldLen = sub(usedHistlen, xLen); + + /* update ltpf-free pcm history buffer for TD-PLC */ + + basop_memmove(&plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - usedHistlen], + &plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - usedHistlen + xLen], oldLen * sizeof(Word16)); + + basop_memcpy(&plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - xLen], &x_fx[0], xLen * sizeof(Word16)); + +#ifdef ENABLE_HR_MODE + frontLen = 0; + IF (sub(fs_idx, 5) < 0) +#endif + { + frontLen = sub(LprotSzPtr[fs_idx], xLen); /*16-10 = 6ms of the prev_synth/xfp part */ + } + pastLen = sub(oldLen, frontLen); /* ~11.8 ms*/ + + marginOldPast = getScaleFactor16_0(&(plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - usedHistlen]), pastLen); + marginOldFront = getScaleFactor16_0(&(plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - usedHistlen + pastLen]), frontLen); + + scale_fac_old = s_min(marginOldFront, marginOldPast); + + frontLen = 0; move16(); + logic16(); logic16(); + IF(bfi == 1 && *prev_bfi == 0 && sub(concealMethod, LC3_CON_TEC_PHASE_ECU) == 0) + { /* prepare localized margin_xfp value for a next bad concealment Method 2 frame */ + frontLen = *nbLostFramesInRow; + frontLen = add(hamm_len2Tab[fs_idx], shr(hamm_len2Tab[fs_idx], 2)); /* find margin in the 3.75 ms front part */ + pastLen = sub(xLen, frontLen); + scale_fac_new = getScaleFactor16_0(&(x_fx[0]), pastLen); + marginNewXlen = getScaleFactor16_0(&(x_fx[0]) + pastLen, frontLen); /* for pHEcuprev_synth in 2nd+ bfi frame */ + + scale_fac_new = s_min(scale_fac_new, marginNewXlen); + } + ELSE + { /* prepare margin value for any coming good frame or any coming first bad frame */ + + marginNewXlen = getScaleFactor16_0(&(x_fx[0]),xLen); /* prevsynth in first bfi frame */ + scale_fac_new = marginNewXlen; move16(); + } + + q_theo_new_old = s_max(plcAd->q_fx_old_exp - scale_fac_old, 0); + q_theo_new_new = s_max(q_fx_exp - scale_fac_new, 0); + + q_new = s_max(q_theo_new_old, q_theo_new_new); + + shift_old = plcAd->q_fx_old_exp - q_new; + shift_new = q_fx_exp - q_new; + + IF(shift_old != 0) + { + Scale_sig(&plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - usedHistlen], oldLen, shift_old); + logic16(); + test(); + IF ((sub(bfi,1) == 0) && (sub(concealMethod, LC3_CON_TEC_TDPLC) == 0)) + { + plcAd->harmonicBuf_Q -= shift_old; + plcAd->tdc_gain_c = L_shl_sat(plcAd->tdc_gain_c, shift_old); + } + move16(); /* count move to static RAM */ + + marginOldFront = s_min(16, sub(marginOldFront, shift_old)); + } + IF(shift_new) + { + Scale_sig(&plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - xLen], xLen, shift_new); /* positive shift_new means upshift=less margin */ + marginNewXlen = s_min(16, sub(marginNewXlen, shift_new)); + } + + plcAd->q_fx_old_exp = sub(q_fx_exp, shift_new); + + plcAd->PhECU_margin_xfp = s_min(marginNewXlen, marginOldFront); move16(); /* for pHECU winEncalc xfp energy calculations */ + if (frontLen != 0) + { /* prepare margin value for a first pHECU(16 ms) or a consecutive bad PhEcu frame (3.75ms) */ + plcAd->PhECU_margin_xfp = marginNewXlen; move16(); + } + if (sub(plcAd->PhECU_margin_xfp, 16) == 0) + { + plcAd->PhECU_margin_xfp = 1; move16(); /* "1" --> does not rescale the all-zero vector, inside PhECU */ + } + } + + /* Update PLC params */ + IF(sub(bfi, 1) != 0) + { + /* % reset counters in GF */ + *nbLostFramesInRow = 0; move16(); + *ns_cum_alpha = 32767; move16(); + + if (plcAd) + { + basop_memmove(plcAd->old_old_scf_q, plcAd->old_scf_q, M * sizeof(Word16)); + basop_memmove(plcAd->old_scf_q, scf_q, M * sizeof(Word16)); + + /* PLC fullband transient detector setting for non-bfi frames */ + plcAd->PhECU_short_flag_prev = 0; move16(); /* fullband transient not active */ + } + } + + /* values may be {0,1,2} */ + *prev_prev_bfi = *prev_bfi; move16(); + *prev_bfi = bfi; move16(); + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +void processPLCcomputeStabFac_main(Word16 scf_q[], Word16 old_scf_q[], Word16 old_old_scf_q[], Word16 bfi, Word16 prev_bfi, + Word16 prev_prev_bfi, Word16 *stab_fac) +{ + IF (sub(bfi, 1) == 0) + { + IF (sub(prev_bfi, 1) != 0) + { + processPLCcomputeStabFac(old_scf_q, old_old_scf_q, prev_prev_bfi, stab_fac); + } + } + ELSE IF(sub(bfi, 2) == 0) + { + processPLCcomputeStabFac(scf_q, old_scf_q, prev_bfi, stab_fac); + } +} + +static void processPLCcomputeStabFac(Word16 scf_q[], Word16 old_scf_q[], Word16 prev_bfi, Word16 *stab_fac) +{ + Counter i; + Word32 tmp32; + Word16 d; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("calculateStabFac", sizeof(struct { + Counter i; + Word32 tmp32; + Word16 d; + })); +#endif + + /* calculate stability factor */ + IF (sub(prev_bfi, 1) == 0) + { + *stab_fac = 26214; move16(); + } + ELSE + { + tmp32 = 0; move32(); + FOR (i = 0; i < M; i++) + { + d = sub(scf_q[i], old_scf_q[i]); + tmp32 = L_mac_sat(tmp32, d, d); + } + tmp32 = L_shl_sat(tmp32, 3); + IF (tmp32 > 0x7D000000 /*1.25*25*/) + { + *stab_fac = 0; move16(); + } + ELSE IF (tmp32 < 0x19003E82 /*0.25*25*/) + { + *stab_fac = 0x7FFF; move16(); + } + ELSE + { + tmp32 = L_shl_pos(L_sub(0x50000000 /*1.25/2*/, Mpy_32_16_lc3plus(tmp32, 0x51EC /*16/25*/)), 1); + *stab_fac = round_fx(tmp32); move16(); + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, Word16 *xfp_fx, Word16 xfp_exp_fx, Word16 margin_xfp, + Word16 fs_idx, + Word32 *L_oold_xfp_w_E_fx, Word16 *oold_xfp_w_E_exp_fx, + Word32 *L_old_xfp_w_E_fx, Word16 *old_xfp_w_E_exp_fx, + + Word16 *oold_Ltot_exp_fx ,Word16 *old_Ltot_exp_fx ) + +{ + Word32 L_tot ; + Word16 dn_scale, exp_shift; + Word16 used_xfp_exp_fx; + Word16 exp_out ; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("PLCUpdateXFP_w_E_hist", sizeof(struct { + Word32 L_tot; + Word16 dn_scale, exp_shift; + Word16 used_xfp_exp_fx; + Word16 exp_out; + })); +#endif +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::UpdateXfp_w_E_hist_fx"); +#endif + + IF (sub(bfi,1) != 0) + { + + if (sub(prev_bfi,1) == 0) + { + /* only a single historic frame available in the next frame + , force artifical update of oold energy to be the same as old */ + *old_xfp_w_E_exp_fx = LTOT_INIT_FLAG ; move16(); + } + + /* Time shift energy state and xfp exp */ + IF (sub_sat(*old_xfp_w_E_exp_fx, LTOT_INIT_FLAG ) == 0) + { + *L_oold_xfp_w_E_fx = LTOT_MIN_MAN ; move32(); + *oold_xfp_w_E_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL ; move16(); + } + ELSE + { + *L_oold_xfp_w_E_fx = *L_old_xfp_w_E_fx; move32(); /* regular update */ + *oold_xfp_w_E_exp_fx = *old_xfp_w_E_exp_fx; move16(); + } + + /* Time shift L_tot energy state and L_tot_exp */ + IF (sub_sat(*old_Ltot_exp_fx, LTOT_INIT_FLAG ) == 0) + { + *L_oold_xfp_w_E_fx = LTOT_MIN_MAN ; move32(); + *oold_Ltot_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL ; move16(); + } + ELSE + { + *L_oold_xfp_w_E_fx = *L_old_xfp_w_E_fx; move32(); /* regular update */ + *oold_Ltot_exp_fx = *old_Ltot_exp_fx; move16(); + } + + + dn_scale = e_tot_headroom[fs_idx]; /* allowed minimum dn_scale for a max upshifted signal */ + used_xfp_exp_fx = xfp_exp_fx; + + IF( margin_xfp > 0 ) /* xfp_fx was normalized on a larger area than 16ms part of pcmBuffer */ + { + ASSERT(bfi !=1) ; /* if bfi was set the margin_xfp does not reflect the correct 16ms part of pcm_buf hist, prev_synth */ + dn_scale = s_max(0, sub(e_tot_headroom[fs_idx], margin_xfp)); + + exp_shift = sub(e_tot_headroom[fs_idx], dn_scale); + used_xfp_exp_fx = sub(xfp_exp_fx, exp_shift); /* the virtual change of the xfp_buffer due to reduced downscaling in L_tot calc */ + } + + /* use semifixed dn_scale as adjusted by margin_xfp in 16 ms region */ + exp_out = xfp_exp_fx; move16(); + L_tot = winEnCalc(xfp_fx, dn_scale , PhECU_wins[fs_idx][0], rectLengthTab[fs_idx], hamm_len2Tab[fs_idx], &exp_out ); + + *L_old_xfp_w_E_fx = L_tot; move32(); + + *old_xfp_w_E_exp_fx = used_xfp_exp_fx ; move16(); + /* this now needs to be in Q1 , used_fx_exp , (exp_out-1-2*e_tot_headroom[fs_idx])/2 */ + + *old_Ltot_exp_fx = exp_out; /* new proper _Ltot value from winEnCalc function */ + + + /* use true Word32 exponent of L_tot */ + + + /* restart oold and old from same state for init or prevBFI cases */ + logic16(); + IF (sub_sat(*oold_xfp_w_E_exp_fx, UNINIT_OR_UNSAFE_OOLD_SENTINEL) <= 0 || /* old xfp_Exp */ + sub_sat(*oold_Ltot_exp_fx, UNINIT_OR_UNSAFE_OOLD_SENTINEL) <= 0 ) /* new L_tot_exp */ + { + *L_oold_xfp_w_E_fx = L_tot; move32(); + *oold_xfp_w_E_exp_fx = used_xfp_exp_fx; move16(); + *oold_Ltot_exp_fx = *old_Ltot_exp_fx; /* use Ltot exp value */ + } + } + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + + diff --git a/lib_lc3plus/plc_update_fx.c b/lib_lc3plus/plc_update_fx.c new file mode 100644 index 000000000..fb05770d5 --- /dev/null +++ b/lib_lc3plus/plc_update_fx.c @@ -0,0 +1,224 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +void processPLCupdate_fx(AplcSetup *plcAd, Word16 x_fx[], Word16 q_fx_exp, Word16 concealMethod, Word16 frame_length, + Word16 fs_idx, Word16 *nbLostFramesInRow, Word16 *prev_prev_bfi, Word16 *prev_bfi, Word16 bfi, Word16 scf_q[], + Word16 *ns_cum_alpha +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif + ) +{ + processPLCUpdateAfterIMDCT_fx(x_fx, q_fx_exp, concealMethod, frame_length, fs_idx, nbLostFramesInRow, prev_prev_bfi, prev_bfi, bfi, + scf_q, ns_cum_alpha, plcAd); /* NB *prev_bfi updated here */ + + IF ( plcAd != 0 ) + { + /* reuse/inplace the most recent 16 ms of x_old_tot without additional rescaling, keep exponent aligned with tdc pitch buffer to save WMOPS */ + + +#ifdef ENABLE_HR_MODE + if (hrmode == 0) +#endif + { + ASSERT( (&plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - LprotSzPtr[fs_idx] ]) == plcAd->PhECU_xfp_fx ); + plcAd->PhECU_xfp_exp_fx = plcAd->q_fx_old_exp; move16(); /* exponent used by concealmethod 2 in prevBfi frames and also right after non bfi frames */ + } + } +} + +void processPLCupdateSpec_fx(Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q_d_fx[], Word16 *q_fx_exp, Word16 yLen) +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word16 s; + ); + + /* save spectrum and the corresponding exponent */ + s = getScaleFactor32_lc3plus(q_d_fx, yLen); + + *q_old_fx_exp = sub(*q_fx_exp, s); + + + FOR (i = 0; i < yLen; i++) + { + q_old_d_fx[i] = round_fx_sat(L_shl_sat(q_d_fx[i], s)); /* */ + } + + Dyn_Mem_Deluxe_Out(); +} + +void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], Word16 yLen, + Word16 *stPhECU_oold_grp_shape_fx, Word16 *stPhECU_old_grp_shape_fx) + +#define L_GRP_DC 4 + +{ + Counter i,l; + Word16 *pX, tmp; + Word16 N_grp,l_grp; + Word16 man, expo; + Word32 L_acc; + Word32 L_tot; + Word32 L_grp_shape[MAX_LGW]; + Word16 grp_shape[MAX_LGW]; /**/ + Word16 fs_idx,local_prev_bfi; + + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("process_plc_spec_2_shape_fx", sizeof(struct { + Counter i,l; + Word16 *pX; + Word16 N_grp,l_grp; + Word32 L_acc; + Word32 L_tot; + Word32 L_grp_shape[MAX_LGW]; + Word16 fs_idx,local_prev_bfi; + })); +#endif +#ifdef WMOPS + BASOP_sub_sub_start("PhECU::GF::process_plc_spec_2_shape_fx"); +#endif + + IF(sub(bfi, 1) != 0) + { + fs_idx = mult(yLen, (Word16)(32768.0 / (99.0))); /* truncation needed , i.e no rounding can be applied here */ + N_grp = xavg_N_grp_fx[fs_idx]; move16(); + + local_prev_bfi = prev_bfi; move16(); + if (sub(local_prev_bfi, 2)==0) + { + local_prev_bfi = 0; move16(); + } + + if( stPhECU_oold_grp_shape_fx[0] < 0 ) + { + local_prev_bfi = 1 ; move16(); /* handle startup in the case 2nd frame is a BFI frame */ + } + + /* Copy old to oold grp shape */ + FOR( i=0; i < MAX_LGW ; i++) + { + stPhECU_oold_grp_shape_fx[i] = stPhECU_old_grp_shape_fx[i]; move16(); + } + + + /* Accumulate DC bin(s) to total */ + pX = q_old_d_fx; /* ptr setup */ + L_tot = L_deposit_h(0); /* acc on negative side */ + + FOR( i= 0; i < L_GRP_DC; i++) + { + tmp = shr_pos(*pX++ ,spec_shape_headroom[fs_idx]); /* scale down upscaled MDCT to create some headroom */ + L_tot = L_msu0(L_tot, tmp, tmp); + + } + + /* Accumulate middle subbands and add to total */ + FOR( i=0; i < sub(N_grp,1) ; i++) + { + + L_acc = L_deposit_h(0); /* acc on negative side */ + l_grp = sub(mdct_grp_bins_fx[i+1], mdct_grp_bins_fx[i]); move16(); + + + + FOR(l=0;l 0) + { + FOR(i=0; i < N_grp ; i++) + { + man = plc_phEcu_ratio_fx(L_grp_shape[i], L_tot, &expo); /* The mantissa is considered in Q15 output in Q14 */ + grp_shape[i] = shr_sat(man, sub(expo,1)); /* gfrom Q14 to in Q15 (Due to saturation, it is automatically bound inside [-1.0,1.0].) */ + } + } + ELSE + { + FOR(i=0; i < N_grp ; i++) + { + grp_shape[i] = GRP_SHAPE_INIT; move16(); + + } + } + + /* copy to output */ + FOR(i=0; i < N_grp ; i++) + { + stPhECU_old_grp_shape_fx[i] = grp_shape[i]; move16(); + } + FOR(i = N_grp; i < MAX_LGW ; i++) + { + stPhECU_old_grp_shape_fx[i] = GRP_SHAPE_INIT; move16(); + } + + + + /* handle oold states for the frame sequence BAD, GOOD, NEXT_BAD */ + if(sub(local_prev_bfi, 1)==0) + { + FOR( i=0; i < MAX_LGW ; i++) + { + stPhECU_oold_grp_shape_fx[i] = stPhECU_old_grp_shape_fx[i] ; move16(); + } + } + + } + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + +} + + + + diff --git a/lib_lc3plus/plc_xcorr_fx.c b/lib_lc3plus/plc_xcorr_fx.c new file mode 100644 index 000000000..720015295 --- /dev/null +++ b/lib_lc3plus/plc_xcorr_fx.c @@ -0,0 +1,250 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" +#include "functions.h" + +#define MAX_ACCS 3 /* sum(x.*y), sum(x.*x), sum(y.*y), nb of always nonsaturated shorter sub_blocks*/ +#define MAX_BLOCKS 8 +#define MAX_ACC_LEN_BITS 7 +#define MIN_ACC_LEN_BITS 5 +#define MAX_ACC_LEN (1 << MAX_ACC_LEN_BITS) +#define MIN_PITCH_8K 20 /* 8000* MIN_PITCH_12k8/12800 */ + +static const Word16 pitch_min_2[] = {2 * MIN_PITCH_8K , 2 * MIN_PITCH_8K * 2, 2 * MIN_PITCH_8K * 3, + 2 * MIN_PITCH_8K * 4, 2 * MIN_PITCH_8K * 6, 2 * MIN_PITCH_8K * 12}; + +/* req headroom in bits, for safe summing of block results w/o downshift */ +/* also the safe pre subblock acc downshift for various number of blocks */ +static const Word16 tab_req_headroom[MAX_BLOCKS + 1] = {0, 0, 1, 2, 2, 3, 3, 3, 3}; +/*(0, 1, 2, 3,4, 5,6,7,8)*/ + +static Word16 plc_norm_corr_blocks_fx(Word16 tot_len, Word16 l2_base_len, Word16 n_blocks, Word16 inshift, + Word16 *currFrame, Word16 *predFrame); + +Word16 plc_norm_corr_blocks_fx( /* o: norm_corr range [-1 ... 1.0[ in Q15 */ + Word16 tot_len, /* i: total correlation length in Q0 */ + Word16 l2_base_len, /* i: size of subblocks in log2 */ + Word16 n_blocks, /* i: number of accumulator sub_blocks */ + Word16 inshift, /* i: required inshift of curr/pred Q0 */ + Word16 *currFrame, /* i: ptr to most recent section */ + Word16 *predFrame) /* i: ptr to historic section */ +{ + Word16 scale0, scale1, scale2, scale_min, shift, prod_exp, acc_margin; + Word32 L_prod, L_inv, L_tmp0 = 0, L_tmp1 = 0, L_tmp2 = 0; + Word16 norm_corr, curr, pred; + Counter m, b; + Word32 L_ce[MAX_ACCS][MAX_BLOCKS]; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("plc_norm_corr_blocks_fx", sizeof(struct { + Word16 scale0, scale1, scale2, scale_min, shift, prod_exp, acc_margin; + Word32 L_prod, L_inv, L_tmp0, L_tmp1, L_tmp2; + Word16 norm_corr, curr, pred; + Counter m, b; + Word32 L_ce[MAX_ACCS][MAX_BLOCKS]; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("plc_norm_corr_blocks_fx"); +#endif + + /* Calculate normalized correlation with added shift and block interleaving possibility */ + ASSERT(n_blocks <= MAX_BLOCKS && n_blocks > 0); + ASSERT(((float)tot_len / (float)n_blocks) <= (float)(1 << l2_base_len)); + ASSERT(inshift > 0); + UNUSED(l2_base_len); + + FOR (b = 0; b < n_blocks; b++) + { /* block loop with fixed pre_down shifting(inshift) of input signal */ + curr = shr_pos(currFrame[b], inshift); + pred = shr_pos(predFrame[b], inshift); + L_tmp2 = L_deposit_l(0); + L_tmp0 = L_msu0(L_tmp2, curr, pred); /* acc L_tmp0 on negative side to avoid saturation for (-1*-1) */ + L_tmp1 = L_msu0(L_tmp2, pred, pred); /* acc_energy on negative side */ + L_tmp2 = L_msu0(L_tmp2, curr, curr); /* acc_energy on negative side */ + + FOR (m = (b + n_blocks); m < tot_len; m += n_blocks) + { /* interleaved accumulation over total length */ + curr = shr_pos(currFrame[m], inshift); + pred = shr_pos(predFrame[m], inshift); + L_tmp0 = L_msu0(L_tmp0, curr, pred); + L_tmp1 = L_msu0(L_tmp1, pred, pred); + L_tmp2 = L_msu0(L_tmp2, curr, curr); + } + + L_ce[0][b] = L_add(L_tmp0, 0); /* account for moves from register to stack memory */ + L_ce[1][b] = L_add(L_tmp1, 0); + L_ce[2][b] = L_add(L_tmp2, 0); + } + + /* aggregate interleaved subsections */ + IF (sub(n_blocks, 1) >= 0) + { /* 100% safe non saturating L_ce with a safe acc_margin */ + acc_margin = tab_req_headroom[n_blocks]; move16(); + + L_tmp0 = L_shr_pos(L_ce[0][0], acc_margin); + L_tmp1 = L_shr_pos(L_ce[1][0], acc_margin); + L_tmp2 = L_shr_pos(L_ce[2][0], acc_margin); + + FOR (b = 1; b < n_blocks; b++) + { + L_tmp0 = L_add(L_tmp0, L_shr_pos(L_ce[0][b], acc_margin)); /* add negative values */ + L_tmp1 = L_add(L_tmp1, L_shr_pos(L_ce[1][b], acc_margin)); /* add negative values */ + L_tmp2 = L_add(L_tmp2, L_shr_pos(L_ce[2][b], acc_margin)); /* add negative values */ + } + + /* evaluate headroom margin in coarse representation */ + scale0 = norm_l(L_tmp0); + scale1 = norm_l(L_tmp1); + scale2 = norm_l(L_tmp2); + + scale_min = s_min(scale0, scale1); + scale_min = s_min(scale_min, scale2); + + shift = sub(scale_min, acc_margin); + IF (shift >= 0) + { /* re-accumulate blocks with highest possible precision */ + L_tmp0 = L_add(L_ce[0][0], 0); /* add negative values */ + L_tmp1 = L_add(L_ce[1][0], 0); /* add negative values */ + L_tmp2 = L_add(L_ce[2][0], 0); /* add negative values */ + + FOR (b = 1; b < n_blocks; b++) + { + L_tmp0 = L_add(L_tmp0, L_ce[0][b]); /* add negative values */ + L_tmp1 = L_add(L_tmp1, L_ce[1][b]); /* add negative values */ + L_tmp2 = L_add(L_tmp2, L_ce[2][b]); /* add negative values */ + } + } + } + + /* quota: norm_corr = corr/sqrt(en1*en2) = negate(L_tmp1)/sqrt(-L_tmp1*-L_tmp2) */ + L_tmp1 = L_min(L_tmp1, -1); /* make sure there is negative energy */ + L_tmp2 = L_min(L_tmp2, -1); /* make sure there is negative energy */ + + ASSERT(L_tmp1 < 0 && L_tmp2 < 0); + + /* negate correlation, due to the used safe msu0 accumulation, with a saturation pre-check ctrl */ + L_tmp0 = L_max(L_tmp0, (MIN_32 + 1)); + L_tmp0 = L_negate(L_tmp0); + + scale0 = norm_l(L_tmp0); + scale1 = norm_l(L_tmp1); + scale2 = norm_l(L_tmp2); + + L_tmp1 = L_shl_pos(L_tmp1, scale1); + L_tmp2 = L_shl_pos(L_tmp2, scale2); + L_prod = Mpy_32_32_lc3plus(L_tmp1, L_tmp2); /* neg * neg -> positive */ + shift = norm_l(L_prod); + L_prod = L_shl_pos(L_prod, shift); + prod_exp = sub(62, add(add(scale1, scale2), shift)); + L_inv = Isqrt(L_prod, &prod_exp); + + L_tmp0 = L_shl_pos(L_tmp0, scale0); + L_prod = Mpy_32_32_lc3plus(L_tmp0, L_inv); + prod_exp = add(sub(31, scale0), prod_exp); + + norm_corr = 32767; move16(); /* as close to 1.0 as possible in Q15 */ + if (L_tmp0 < 0) + { + norm_corr = -32768; move16(); /*-1.0*/ + } + + test(); + IF (L_prod == 0 || sub(norm_l(L_prod), prod_exp) >= 0) + { + norm_corr = round_fx_sat(L_shl_sat(L_prod, prod_exp)); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return norm_corr; +} + +Word16 plc_xcorr_lc_fx( /* o: quantized output xcorr in Q15 [ 0 ..32767 ] = [0. 1.0[ */ + Word16 *pcmbuf_fx, /* i: NB should be an already dynamically upscaled pcm buffer with about + 0...1(2) bits margin */ + Word16 max_len_pcm_plc, /* i: Q0 physical size of pcmbuf_fx */ + Word16 pitch_int, /* i: Q0 in Fs, lag value to evaluate, corresponding to the current f0 in + pcm_buf_Fx */ + Word16 fs_idx /*i: */) +{ + Word16 *range1Ptr; + Word16 *range2Ptr; + Word16 corr_len_fx, inshift, l2_base_len, n_blocks, norm_xcorr_est_q, pcm_max_corr_len, max_corr_len; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("plc_xcorr_lc_fx", sizeof(struct { + Word16 *range1Ptr; + Word16 *range2Ptr; + Word16 corr_len_fx, inshift, l2_base_len, n_blocks, norm_xcorr_est_q, pcm_max_corr_len, max_corr_len; + })); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("plc_xcorr_lc_fx"); +#endif + + norm_xcorr_est_q = 0; move16(); + + IF (pitch_int > 0) + { + pcm_max_corr_len = sub(max_len_pcm_plc, pitch_int); + + max_corr_len = rectLengthTab[fs_idx]; /* maximum 10 ms */ + max_corr_len = s_min(max_corr_len, pcm_max_corr_len); + + corr_len_fx = s_min(max_corr_len, pitch_int); + corr_len_fx = s_max(corr_len_fx, pitch_min_2[fs_idx]); /* at least 5 ms (=2*pitchmin*) corr length */ + + ASSERT(corr_len_fx >= (pitch_min_2[fs_idx])); /* at least 2 x pitch min(fs) */ + ASSERT(corr_len_fx <= (MAX_ACC_LEN * MAX_BLOCKS)); + ASSERT(corr_len_fx <= max_corr_len); + ASSERT( max_len_pcm_plc - corr_len_fx - pitch_int + 1 > 0 ); + + range1Ptr = &(pcmbuf_fx[max_len_pcm_plc]) - corr_len_fx; /* ptr setup, start of head section */ + range2Ptr = range1Ptr - pitch_int; /* ptr setup, history = tail - lag distance */ + + /* assume 32 bit acc of up to 32 values -> sum(over 32, x_up>>2 * y_up>>2) */ + inshift = 2; move16(); + l2_base_len = MIN_ACC_LEN_BITS; move16(); + n_blocks = shr(add(corr_len_fx, (1 << MIN_ACC_LEN_BITS) - 1), MIN_ACC_LEN_BITS); + + IF (sub(n_blocks, MAX_BLOCKS) > 0) + { /* shift to 32 bit acc of up to 128 values -> sum(over 128, x_up>>3 * y_up>>3) */ + inshift = 3; move16(); + l2_base_len = MAX_ACC_LEN_BITS; move16(); + n_blocks = shr(add(corr_len_fx, ((1 << MAX_ACC_LEN_BITS) - 1)), MAX_ACC_LEN_BITS); + } + + ASSERT(n_blocks <= MAX_BLOCKS); /* MAX_BLOCKS*(32 or 128) is max possible total corr_length */ + ASSERT(n_blocks > 0); + + /* subblock accumulation of corr and energies, to achieve high low level precision */ + norm_xcorr_est_q = + plc_norm_corr_blocks_fx(corr_len_fx, l2_base_len, n_blocks, inshift, range1Ptr, /* curr_frame */ + range2Ptr); /* pred_frame = curr_frame-lag, i.e historic section */ + + norm_xcorr_est_q = s_max(0, norm_xcorr_est_q); /* do not allow negative output values */ + } +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + return norm_xcorr_est_q; +} + + diff --git a/lib_lc3plus/pvq_dec_fx.c b/lib_lc3plus/pvq_dec_fx.c new file mode 100644 index 000000000..d77aae809 --- /dev/null +++ b/lib_lc3plus/pvq_dec_fx.c @@ -0,0 +1,153 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +Word16 pvq_dec_deidx_fx( /* out BER detected 1 , ok==0 */ + Word16 * y, /* o: decoded vector (non-scaled int) */ + const Word16 k_val, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 LS_ind, /* i; lS index 1 bit */ + const UWord32 UL_MPVQ_ind /* i; MPVQ index */ +) +{ + Dyn_Mem_Deluxe_In( + Word16 BER_flag; + UWord32 h_mem[1 + KMAX_FX + 1]; + PvqEntry_fx entry; + ); + + BER_flag = 0; move16(); + + /* get_size will likely be called before this function, as the range decoder needs the size to fetch the index + */ + entry = get_size_mpvq_calc_offset_fx(dim, k_val, h_mem); /* TBD should be made into tables for N=16,10,6 */ + + entry.lead_sign_ind = LS_ind; move16(); + entry.index = L_deposit_l(0); /* only in case dim == 1 */ + IF (sub(dim, 1) != 0) + { + entry.index = UL_MPVQ_ind; + + /* safety check in case of bit errors */ + IF (L_sub(entry.index, entry.size) >= 0) + { + BER_flag = 1; move16(); + entry.index = 0; move16(); /* return something deterministic/valid, and LOW complex */ + } + } + mpvq_deindex_fx(&entry, h_mem, y); /* actual deindexing */ + + Dyn_Mem_Deluxe_Out(); + return BER_flag; +} + + + +#ifdef ENABLE_HR_MODE +void pvq_dec_scale_vec_fx(const Word32 *inQ29, Word16 adjGainQ13, Word32 *outQ) +#else +void pvq_dec_scale_vec_fx(const Word16 *inQ14, Word16 adjGainQ13, Word16 *outQ14) +#endif +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + FOR (i = 0; i < M; i++) + { +#ifdef ENABLE_HR_MODE + outQ[i] = L_shr(L_add(outQ[i], Mpy_32_16_lc3plus(inQ29[i], adjGainQ13)), 1); + move16(); +#else + outQ14[i] = add(outQ14[i], mult_r(adjGainQ13, inQ14[i])); move16(); +#endif + } + Dyn_Mem_Deluxe_Out(); +} + + +void pvq_dec_en1_normQ14_fx(/* Have to be used EXACTLY the same way in both both encoder and decoder */ +#ifdef ENABLE_HR_MODE + Word32 * xq, /* o: en1 normalized decoded vector (Q14) */ +#else + Word16 * xq, /* o: en1 normalized decoded vector (Q14) */ +#endif + const Word16 *y, /* i: decoded vector (non-scaled int) */ + const Word16 k_val_max, + /* i: max possible K in Q0 kO or kA */ /* OPT: not BE , use dynamic max pulse + amplitude */ + const Word16 dim /* i: Length of vector */ +) +{ +#ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_tmp; + Word16 shift_num, shift_tot; + Word32 isqrtQ31_local; + Word16 tmp, exp, exp_shift; + Word32 L_yy; + ); +#else + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_tmp; + Word16 shift_num, shift_tot; + Word16 isqrtQ16_local, tmp, exp, exp_shift; + Word32 L_yy; + ); +#endif + +/* energy normalization starts here */ + L_yy = L_mult0(y[0], y[0]); + FOR (i = 1; i < dim; i++) + { + L_yy = L_mac0(L_yy, y[i], y[i]); /* stay in Q0 */ /* OPT: reuse some energies from PVQ linear search */ + } + /* 16 bit */ + IF (L_sub(L_yy, SQRT_EN_MAX_FX) < 0) + { + ASSERT(L_yy > 4); /* Q16 isqrt table lookup not valid below 5 */ +#ifdef ENABLE_HR_MODE + isqrtQ31_local = isqrt_Q31tab[L_yy]; move16(); /* 1 cycle */ +#else + isqrtQ16_local = isqrt_Q16tab[L_yy]; move16(); /* 1 cycle */ +#endif + } + ELSE + { + /* about 8-9 cycles */ + exp = 15; move16(); /* set ISqrt16() exp_in to get delta exp out near 0 when Lyy is in Q0 */ + tmp = ISqrt16(extract_l(L_yy), + &exp); /* exp out is now a delta shift with a later tmp Q15 multiplication in mind */ +#ifdef ENABLE_HR_MODE + exp_shift = add(exp, 16); /* up to Q16 */ + isqrtQ31_local = L_shl(L_deposit_l(tmp), exp_shift); /* new mantissa in a fixed Q16 */ +#else + exp_shift = add(exp, 16 - 15); /* up to Q16 */ + isqrtQ16_local = shl(tmp, exp_shift); /* new mantissa in a fixed Q16 */ +#endif + } + + shift_num = norm_s(k_val_max); /* simply account for the preknown fixed max possible pulseamp in y */ + shift_tot = sub(14 - 1, shift_num); /* upshift to get to Q14 */ + FOR (i = 0; i < dim; i++) /* upshifted y[i] used */ + { +#ifdef ENABLE_HR_MODE + L_tmp = Mpy_32_16_lc3plus(isqrtQ31_local, shl_pos(y[i], shift_num)); /* Q(16+0+shift_num +1 = shift_num+1 */ + xq[i] = L_shl(L_tmp, shift_tot + 1); move32(); /* Q30 , */ +#else + L_tmp = L_mult(isqrtQ16_local, shl_pos(y[i], shift_num)); /* Q(16+0+shift_num +1 = shift_num+1 */ + xq[i] = round_fx(L_shl(L_tmp, shift_tot)); move16(); /* Q14 , */ +#endif + } + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/pvq_enc_fx.c b/lib_lc3plus/pvq_enc_fx.c new file mode 100644 index 000000000..9c164dda5 --- /dev/null +++ b/lib_lc3plus/pvq_enc_fx.c @@ -0,0 +1,369 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static void pvq_pyr_project(const Word16 dim_proj, /* end vector dimension+1 */ + const Word16 *xabs, /* absolute vector values */ + Word32 L_xsum, /* absolute vector sum over dim */ + Word16 num, /* target number of pulses */ + Word16 * y, /* projected output vector */ + Word16 *pulse_tot_ptr, Word32 *L_xy_ptr, /* accumulated correlation Q(in+0+1) = Qin+1 */ + Word32 *L_yy_ptr /* accumulated energy Q0 */ +) +{ + + Dyn_Mem_Deluxe_In( + Counter i; + Word32 L_tmp, L_num; + Word16 den, shift_num, shift_den, shift_delta, proj_fac; + ); + + *pulse_tot_ptr = 0; move16(); + *L_xy_ptr = L_deposit_l(0); + *L_yy_ptr = L_deposit_l(0); + + shift_den = norm_l(L_xsum); /* x_sum input Qin */ + den = extract_h(L_shl_pos(L_xsum, shift_den)); /* now in Qin+shift_den */ + + L_num = L_deposit_l(num); + shift_num = sub(norm_l(L_num), 1); + L_num = L_shl_pos(L_num, shift_num); /* now in Q0 +shift_num -1 */ + proj_fac = div_l(L_num, den); /* L_num always has to be less than den<<16 , norm_l-1 makes that happen */ + + shift_delta = sub(shift_num, shift_den); + FOR (i = 0; i < dim_proj; i++) + { + L_tmp = L_mult(proj_fac, xabs[i]); /* Q shift_delta + PVQ_SEARCH_QIN */ + y[i] = extract_h(L_shr(L_tmp, shift_delta)); move16(); /* to Q0 with floor , and potential sturation */ + ; + + *pulse_tot_ptr = add(*pulse_tot_ptr, y[i]); /* Q0 */ + *L_yy_ptr = L_mac0(*L_yy_ptr, y[i], y[i]); /* Energy, Q0 */ + *L_xy_ptr = L_mac(*L_xy_ptr, xabs[i], y[i]); /* Corr, Q0*Q12 +1 --> Q13 */ + } + + Dyn_Mem_Deluxe_Out(); +} + + +static __forceinline Word16 one_pulse_search(const Word16 dim_start, /* start vector dimension */ + const Word16 dim_end, /* end vector dimension+1 */ + const Word16 *x_abs, /* absolute vector values */ + Word16 * y, /* output vector */ + Word16 * pulse_tot_ptr, + Word32 * L_xy_ptr, /* accumulated correlation Q(12+0+1) = Q13 */ + Word32 * L_yy_ptr, /* accumulated energy Q0 */ + Word16 max_xabs) /* current max amplitude for target */ +{ + Dyn_Mem_Deluxe_In( + Counter i; + Word16 corr_tmp, corr_sq_tmp, en_max_den, cmax_num, en_tmp; + Word32 L_tmp_en_lc, L_tmp_corr; + Word16 corr_up_shift, imax; + ); + + /* maximize correlation precision, prior to every unit pulse addition in the vector */ + corr_up_shift = norm_l(L_mac(*L_xy_ptr, 1, max_xabs)); /* pre analyze worst case L_xy update in the dim loop */ + imax = -1; /* not needed for search, only added to avoid compiler warning */ + { + en_max_den = 0; move16(); + cmax_num = -1; move16(); /* req. to force a 1st update for n==dim_start */ + + FOR (i = dim_start; i < dim_end; i++) + { + L_tmp_corr = L_shl_pos(L_mac(*L_xy_ptr, 1, x_abs[i]), corr_up_shift); /* actual in-loop target value */ + + corr_tmp = round_fx_sat(L_tmp_corr); + + corr_sq_tmp = mult(corr_tmp, corr_tmp); /* CorrSq_tmp for a 16bit low complexity cross multiplication */ + + L_tmp_en_lc = L_mac(*L_yy_ptr, 1, y[i]); /*Q0 x^2+ 2x , "+1" added once before loop , result , energy may + span up to ~14+1(Q1)+1(sign)=16 bits */ + /* extract_l without shift can always be used for this section as energy is guaranteed to stay in the lower + * word*/ + + en_tmp = extract_l(L_tmp_en_lc); /* L_shl + round_fx could also be used also but then adds an uphift cost */ + + /* 16/32 bit comparison WC (4 +1+1 + (1+1+1) = 9 */ + IF (L_msu(L_mult(corr_sq_tmp, en_max_den), cmax_num, en_tmp) > 0) /* use L_mult and then a L_msu */ + { + cmax_num = corr_sq_tmp; move16(); + en_max_den = en_tmp; move16(); + imax = i; move16(); + } + } /* dim */ + } + + + /* finally add found unit pulse contribution to past L_xy, Lyy, for next pulse loop */ + *L_xy_ptr = L_mac(*L_xy_ptr, x_abs[imax], 1); /* Qin+1 */ + *L_yy_ptr = L_mac(*L_yy_ptr, 1, y[imax]); + + y[imax] = add(y[imax], 1); move16(); /* Q0 added pulse */ + (*pulse_tot_ptr) = add((*pulse_tot_ptr), 1); /* increment total pulse sum */ + Dyn_Mem_Deluxe_Out(); + return imax; +} + + +void pvq_enc_search_fx( + const Word16 *x, /* i: target vector to quantize Qin */ + Word16 * y_far, /* o: outl_far o, raw pulses (non-scaled short) Q0 , length dim */ + Word16 * y, /* o: outl_near o, raw pulses (non-scaled short) Q0 , length dim */ + Word16 * yA, /* o: A section raw pulses (non-scaled short) Q0 , length dimA */ + Word16 * yB, /* o: B section raw pulses (non-scaled short) Q0 , length dim-dimA */ + Word32 * L_corr, /* o: 4 un-normalized correlation sums for outl_far, outl_near, A, AB */ + Word32 * L_search_en, /* o: 4 energy sums for outl_far, outl_near, A, AB */ + Word16 * pulses_fin, /* i: number of allocated pulses to outl_far, outl_near , A, AB sections */ + Word16 * pulses_proj, /* i: number of projection pulses for outl_far, outl_near, A, AB */ + + const Word16 dim, /* i: Length of outlier vector */ + const Word16 dimA /* i: Length of vector A section */ +) +{ + + Dyn_Mem_Deluxe_In( + Counter i; + Word16 pulse_tot_far, pulse_tot, pulse_totA, pulse_totB; + Word16 xabs[PVQ_MAX_VEC_SIZE]; + Word16 max_xabs, max_xabsA, max_xabsB; + Word32 L_xsum, L_xsumA; + Word32 L_yy, L_xy; + Word16 imax; + Counter k; + Word16 dim_m1; + Word16 dimB; + const Word16 *xBptr; + Word16 pulses_far, pulses, pulsesA, pulsesB; + ); + +#ifdef WMOPS + BASOP_sub_sub_start("pvq_enc_search_fx"); +#endif + + pulses_far = pulses_fin[0]; move16(); + pulses = pulses_fin[1]; move16(); + pulsesA = pulses_fin[2]; move16(); + pulsesB = pulses_fin[3]; move16(); + + FOR (i = 0; i < N_SCF_SHAPES_ST2; i++) + { + L_corr[i] = L_deposit_l(0); + L_search_en[i] = L_deposit_l(0); + } + + dimB = sub(dim, dimA); + + L_xsum = L_deposit_h(0); + + max_xabs = -1; move16(); + max_xabsA = -1; move16(); + max_xabsB = -1; move16(); + FOR (i = 0; i < dimA; i++) + { + xabs[i] = abs_s(x[i]); move16(); /* Qx */ + max_xabsA = s_max(max_xabsA, xabs[i]); /* for efficient search correlation scaling */ + L_xsum = L_mac0(L_xsum, 1, xabs[i]); /* stay in Qx */ + } + + basop_memset(y_far, 0, dim * sizeof(Word16)); + basop_memset(y, 0, dimA * sizeof(Word16)); + basop_memset(yA, 0, dimA * sizeof(Word16)); + + L_xsumA = L_add(L_xsum, 0); /* save for section A projection */ + + FOR (i = dimA; i < dim; i++) + { + xabs[i] = abs_s(x[i]); move16(); /* Qx */ + max_xabsB = s_max(max_xabsB, xabs[i]); /* for efficient search correlation scaling */ + L_xsum = L_mac0(L_xsum, 1, xabs[i]); /* stay in Qx */ + } + + basop_memset(&y[dimA], 0, (dim - dimA) * sizeof(Word16)); + + basop_memset(yB, 0, dimB * sizeof(Word16)); + + max_xabs = s_max(max_xabsA, max_xabsB); /* global max abs value */ + + test(); + IF (L_xsum == 0) + { /* no shape in any section, projection in outl_far, outl_near, A, AB not possible, any search meaningless */ + + dim_m1 = sub(dim, 1); + y_far[0] = shr_pos(pulses_far, 1); move16(); + y_far[dim_m1] = add(y_far[dim_m1], sub(pulses_far, y_far[0])); move16(); + + dim_m1 = sub(dim, 1); + y[0] = shr_pos(pulses, 1); move16(); + y[dim_m1] = add(y[dim_m1], sub(pulses, y[0])); move16(); + + dim_m1 = sub(dimA, 1); + yA[0] = shr_pos(pulsesA, 1); move16(); + yA[dim_m1] = add(yA[dim_m1], sub(pulsesA, yA[0])); move16(); + + dim_m1 = sub(dimB, 1); + yB[0] = shr_pos(pulsesB, 1); move16(); + yB[dim_m1] = add(yB[dim_m1], sub(pulsesB, yB[0])); move16(); + } + ELSE + { + ASSERT(pulses_proj[0] > 0); + ASSERT(L_xsum > 0); + + pvq_pyr_project(dim, xabs, L_xsum, pulses_proj[0], y_far, &pulse_tot_far, &L_xy, + &L_yy); /* outlier submode projection */ + + ASSERT(pulses_far <= 127); + FOR (k = pulse_tot_far; k < pulses_far; k++) + { + L_yy = L_add(L_yy, 1); /* pre add 1 in Q0 in L_yyQ0 = (x^2 + 2*x + 1) */ + imax = one_pulse_search(0, dim, xabs, y_far, &pulse_tot_far, &L_xy, &L_yy, max_xabs); + } + ASSERT(pulse_tot_far == pulses_far); + /* outlier far submode result vector in y_far[0...15] */ + L_corr[0] = L_shr_pos(L_xy, 1); /* to Qin*Q0 */ + + basop_memmove(y, y_far, dim * sizeof(Word16)); /*y_far->y */ + + pulse_tot = pulse_tot_far; move16(); + + ASSERT(pulses <= 127); + FOR (k = pulse_tot; k < pulses; k++) + { + L_yy = L_add(L_yy, 1); /* pre add 1 in Q0 in L_yyQ0 = (x^2 + 2*x + 1) */ + imax = one_pulse_search(0, dim, xabs, y, &pulse_tot, &L_xy, &L_yy, max_xabs); + } + + /* outlier near submode result vector in y[0...15] */ + L_corr[1] = L_shr_pos(L_xy, 1); /* to Qin*Q0 */ + + ASSERT(pulse_tot == pulses); + + IF (L_xsumA == 0) + { + /* no shape in A section, projection in A not possible, search meaningless */ + dim_m1 = sub(dimA, 1); + yA[0] = shr_pos(pulsesA, 1); move16(); + yA[dim_m1] = add(yA[dim_m1], sub(pulsesA, yA[0])); move16(); + } + ELSE + { + IF (pulses_proj[2] != 0) /* fixed setup if bitrate is fixed */ + { + ASSERT(pulses_proj[2] > 0); + ASSERT(L_xsumA > 0); + pvq_pyr_project(dimA, xabs, L_xsumA, pulses_proj[2], yA, &pulse_totA, &L_xy, + &L_yy); /* section A , in submode 1 projection */ + } + ELSE + { + /* default, otherwise recalculate A from outlier result (to remove any section B pulses influence) + */ + pulse_totA = 0; move16(); + L_xy = L_deposit_l(0); + L_yy = L_deposit_l(0); + + basop_memmove(yA, y, dimA * sizeof(Word16)); + FOR (i = 0; i < dimA; i++) + { + pulse_totA = add(pulse_totA, yA[i]); /* Q0 */ + L_xy = L_mac(L_xy, xabs[i], yA[i]); /* Corr, Q0*Q12 +1 --> Q13 */ + L_yy = L_mac(L_yy, yA[i], yA[i]); /* Energy, Q(0+0)+1)= Q1 */ + } + L_yy = L_shr_pos(L_yy, 1); /* En to Q0 */ + } + + /* search remaining pulses in regular section A */ + FOR (k = pulse_totA; k < pulsesA; k++) + { + L_yy = L_add(L_yy, 1); /* 1 added in Q0 */ + imax = one_pulse_search(0, dimA, xabs, yA, &pulse_totA, &L_xy, &L_yy, max_xabsA); + } + ASSERT(pulse_totA == pulsesA); + } /* L_xsumA!=0 */ + + /* reg Set A result vector now in yA[0...9] */ + L_corr[2] = L_shr_pos(L_xy, 1); /* to Qin*Q0 */ + + /* search remaining pulses in regular section B, even if energy in B is zero */ + ASSERT(pulses_proj[3] == 0); + pulse_totB = 0; move16(); + + IF (sub(pulsesB, 1) == 0) + { /* LC search, sufficient to find a single max, as pulses can not be stacked, when nb-pulses==1 */ + imax = 0; move16(); /* safety */ + FOR (i = dimA; i < dim; i++) + { + if (xabs[i] == max_xabsB) + { + imax = sub(i, dimA); + } + } + pulse_totB = 1; move16(); + yB[imax] = 1; move16(); /* reg set B result vector in yB[0...5] */ + L_xy = L_mac(L_xy, xabs[add(imax, dimA)], 1); /* calc total corr for A+B sections */ + L_yy = L_add(L_yy, 1); + } + ELSE + { /* more than one target pulse in section B */ + /* keep A pulses influence, search section B pulses influence */ + FOR (k = pulse_totB; k < pulsesB; k++) + { + L_yy = L_add(L_yy, 1); /* 1 added in Q0*/ + imax = one_pulse_search(dimA, dim, xabs, &(yB[-dimA]), &pulse_totB, &L_xy, &L_yy, max_xabsB); + } + } + + L_corr[3] = L_shr_pos(L_xy, 1); move32(); /* to Qin*Q0 , corr of combined A and B */ + + ASSERT(pulse_totB == pulsesB); + /* reg set B result vector now in yB[0...5] */ + } /* L_xsum != 0 */ + +/* apply sign of (x) to first orthant result */ + FOR (i = 0; i < dim; i++) + { + if (x[i] < 0) + { + y_far[i] = negate(y_far[i]); /* apply sign for outlier far */ + } + } + + FOR (i = 0; i < dim; i++) + { + if (x[i] < 0) + { + y[i] = negate(y[i]); /* apply sign for outliers near */ + } + } + + xBptr = &(x[dimA]); move32(); /* ptr init to B target section */ + FOR (i = 0; i < dimA; i++) + { + if (x[i] < 0) + { + yA[i] = negate(yA[i]); /* apply sign in N_SETA */ + } + } + + FOR (i = 0; i < (dimB); i++) + { + if (xBptr[i] < 0) + { + yB[i] = negate(yB[i]); /* apply sign in N_SETB */ + } + } + + Dyn_Mem_Deluxe_Out(); +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} + diff --git a/lib_lc3plus/pvq_index_fx.c b/lib_lc3plus/pvq_index_fx.c new file mode 100644 index 000000000..c7d63c840 --- /dev/null +++ b/lib_lc3plus/pvq_index_fx.c @@ -0,0 +1,513 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +#define SIGNBIT_FX 0x80000000u +#define SIGNBIT_SHRT_FX 0x8000 + +static void initOffsets_fx(Word16 dim_in, UWord32 *h_mem, + Word16 k_val_in) /* may be removed with tables for N=16,10,6 */ +{ + UWord32 k_val_prev, k_val_curr; + UWord32 k_val, UL_k_val_in; +#ifdef DYNMEM_COUNT + Dyn_Mem_In("initOffsets_fx", sizeof(struct { + UWord32 k_val_prev, k_val_curr; + UWord32 k_val, UL_k_val_in; + })); +#endif + + h_mem[0] = UL_deposit_l(0); + h_mem[1] = UL_deposit_l(1); + + UL_k_val_in = UL_deposit_l(k_val_in); + IF (sub(dim_in, 2) == 0) + { + FOR (k_val = 2; k_val <= UL_k_val_in; k_val++) + { + h_mem[k_val] = UL_subNsD(UL_lshl(k_val, 1), 1U); move32(); + } + h_mem[k_val] = UL_k_val_in; move32(); + } + ELSE + { + k_val_prev = UL_deposit_l(1U); + FOR (k_val_curr = 2; k_val_curr <= UL_k_val_in; k_val_curr++) + { + h_mem[k_val_curr] = UL_addNsD(1U, UL_Mpy_32_32(k_val_curr, UL_lshl(k_val_prev, 1))); move32(); + k_val_prev = UL_addNsD(k_val_curr, 0U); + } + h_mem[k_val_curr] = UL_Mpy_32_32(k_val_curr, k_val_prev); move32(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +static void a_fwd_fx(UWord32 *a_in, /* i/o: offsets */ + Word16 n_items /* i : items, k's */ +) +{ + UWord32 a_1, a_in0; + Counter i; + UWord32 *a_in_prev_ptr; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("a_fwd_fx", sizeof(struct { + UWord32 a_1, a_in0; + Counter i; + UWord32 *a_in_prev_ptr; + })); +#endif + + a_in0 = UL_deposit_l(1); + + a_in_prev_ptr = &(a_in[-1]); + FOR (i = 1; i <= n_items; i++) + { + a_1 = UL_addNsD(a_in0, UL_addNsD(a_in_prev_ptr[i], a_in[i])); + a_in_prev_ptr[i] = a_in0; move32(); + a_in0 = UL_addNsD(a_1, 0U); + } + a_in_prev_ptr[i] = a_in0; move32(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +static void a_bwd_fx(UWord32 *a_in, /* i/o: offsets */ + Word16 n_items /* i: n_items */ +) +{ + UWord32 a_1, a_in0; + Counter i; + UWord32 *a_in_prev_ptr; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("a_bwd_fx", sizeof(struct { + UWord32 a_1, a_in0; + Counter i; + UWord32 *a_in_prev_ptr; + })); +#endif + + a_in0 = UL_deposit_l(0); + a_in_prev_ptr = &(a_in[-1]); + + FOR (i = 1; i <= n_items; i++) + { + a_1 = UL_subNsD(UL_subNsD(a_in[i], a_in0), a_in_prev_ptr[i]); + a_in_prev_ptr[i] = a_in0; move32(); + a_in0 = UL_addNsD(a_1, 0U); + } + a_in_prev_ptr[i] = a_in0; move32(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +static void a_u_fwd_fx(UWord32 *a_u_in, Word16 k_val_in, Word16 mem_size_m1) +{ + UWord32 u_kp1_prev, u_kp1; + UWord32 u_k_prev; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("a_u_fwd_fx", sizeof(struct { + UWord32 u_kp1_prev, u_kp1; + UWord32 u_k_prev; + })); +#endif + + u_kp1_prev = a_u_in[mem_size_m1]; move32(); + u_k_prev = UL_lshr(a_u_in[k_val_in], 1); + + a_fwd_fx(&a_u_in[1], k_val_in); + + u_kp1 = UL_lshr(a_u_in[k_val_in], 1); + a_u_in[mem_size_m1] = UL_addNsD(1U, UL_addNsD(u_kp1_prev, UL_addNsD(u_k_prev, u_kp1))); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +static Word16 get_lead_sign_fx(UWord32 *ind) +{ + Word16 leading_sign; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("get_lead_sign_fx", sizeof(struct { Word16 leading_sign; })); +#endif + + leading_sign = 1; move16(); + if (UL_and(*ind, 1) != 0) + { + leading_sign = -1; move16(); + } + (*ind) = UL_lshr(*ind, 1); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + + return leading_sign; +} + +/*-------------------------------------------------------------------* + * mind2vec_one_fx() + *-------------------------------------------------------------------*/ +static void mind2vec_one_fx(Word16 k_val_in, /* i: nb unit pulses , [ 0...K_MAX ] */ + Word16 leading_sign, /* i: leading sign -1, 0, 1*/ + UWord32 ind, /* i: index */ /* parameter could be omitted */ + Word16 *vec_out /* o: pulse train */ +) +{ + *vec_out = (Word16)ind; /* dummy assignment to handle the common ind parameter warning */ + + if (leading_sign < 0) + { + k_val_in = negate(k_val_in); + } + *vec_out = k_val_in; move16(); +} + +static Word16 setval_update_sign_fx(Word16 k_delta, Word16 k_max_local, Word16 *leading_sign, UWord32 *ind_in, + Word16 *vec_out) +{ + IF (k_delta != 0) + { + mind2vec_one_fx(k_delta, *leading_sign, *ind_in, vec_out); + *leading_sign = get_lead_sign_fx(ind_in); + k_max_local = sub(k_max_local, k_delta); + } + return k_max_local; +} + +/*-------------------------------------------------------------------* + * mind2vec_fx() + *-------------------------------------------------------------------*/ +static void mind2vec_fx(Word16 dim_in, /* i: dimension */ + Word16 k_max_local, /* i: nb unit pulses */ + Word16 leading_sign, /* i: leading sign */ + UWord32 ind, /* i: index */ + Word16 * vec_out, /* o: pulse train */ + UWord32 *h_in /* i: offset vector A=1+2U */ +) +{ + Counter pos; + Word16 k_acc, k_delta; + UWord32 UL_tmp_offset, UL_diff; + UWord16 sgn; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("mind2vec_fx", sizeof(struct { + Counter pos; + Word16 k_acc, k_delta; + UWord32 UL_tmp_offset, UL_diff; + UWord16 sgn; + })); +#endif + + k_acc = k_max_local; move16(); + FOR (pos = 0; pos < dim_in; pos++) + { + + IF (ind != 0) + { + + k_acc = k_max_local; move16(); + + UL_tmp_offset = UL_addNsD(h_in[k_acc], 0U); + + UL_diff = UL_subNs(ind, UL_tmp_offset, &sgn); + + WHILE (sgn) + { + UL_diff = UL_subNs(ind, h_in[--k_acc], &sgn); + } + + ind = UL_addNsD(UL_diff, 0U); + + k_delta = sub(k_max_local, k_acc); + } + ELSE + { + mind2vec_one_fx(k_max_local, leading_sign, ind, &vec_out[pos]); + BREAK; + } + + k_max_local = setval_update_sign_fx(k_delta, k_max_local, &leading_sign, &ind, &vec_out[pos]); + + a_bwd_fx(h_in, add(k_max_local, 1)); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +PvqEntry_fx get_size_mpvq_calc_offset_fx( /* o : size, dim, k_val */ + Word16 dim_in, /* i : dimension */ + Word16 k_val_in, /* i : nb unit pulses */ + UWord32 *h_mem /* o : offsets */ +) +{ + Counter i; + PvqEntry_fx entry; + Word16 kp1; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("get_size_mpvq_calc_offset_fx", sizeof(struct { + Counter i; + PvqEntry_fx entry; + Word16 kp1; + })); +#endif + + entry.dim = dim_in; move16(); + entry.k_val = k_val_in; move16(); + + entry.index = L_deposit_l(0); + entry.lead_sign_ind = 0; move16(); + + ASSERT(dim_in <= M); + ASSERT(tabledKMAX[dim_in] != 0); + + /* tabled values for worst case K */ /* made into table lookup for N=16, 10, 6 */ + kp1 = add(k_val_in, 1); + FOR (i = 0; i <= kp1; i++) /* A+U copying */ + { + h_mem[i] = + UL_addNsD(MPVQ_offs_ptr[dim_in][i], 0U); /* a vector copying is needed as MPVQ recursion is in place */ + } + /* special handling of last U offset in k+1 column */ + if (sub(k_val_in, tabledKMAX[dim_in]) != 0) + { + h_mem[kp1] = UL_lshr(h_mem[kp1], 1); /* (A+1)/2 , convert from A(K+1) to U(K+1) domain */ + } + entry.size = + UL_addNsD(1U, UL_addNsD(h_mem[kp1], UL_lshr(h_mem[k_val_in], 1))); /* MPVQ size calc. 1 + H(K+1) + (A(K)>>1) */ + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + + return entry; +} + +/*-------------------------------------------------------------------* + * mpvq_deindex_fx() + *-------------------------------------------------------------------*/ +void mpvq_deindex_fx( /* o : void */ + const PvqEntry_fx *entry, /* i : sign_ind, index, dim, k_val */ + UWord32 * h_mem, /* i : A/U offsets */ + Word16 * vec_out /* o : pulse train */ +) +{ + Word16 leading_sign; +#ifdef DYNMEM_COUNT + Dyn_Mem_In("mpvq_deindex_fx", sizeof(struct { Word16 leading_sign; })); +#endif +#ifdef WMOPS + BASOP_sub_sub_start("mpvq_deindex_fx"); +#endif + + basop_memset(vec_out, 0, (entry->dim) * sizeof(Word16)); + + leading_sign = 1; move16(); + if (entry->lead_sign_ind != 0) + { + leading_sign = -1; move16(); + } + + IF (entry->k_val != 0) + { + mind2vec_fx(entry->dim, entry->k_val, leading_sign, entry->index, vec_out, h_mem); + } +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +} + +/*-------------------------------------------------------------------* + * vec2mind_two_fx() + *-------------------------------------------------------------------*/ +static void vec2mind_two_fx(const Word16 *vec_in, /* i : PVQ pulse train */ + Word16 * k_val_out_ptr, /* o : number of unit pulses */ + UWord32 * next_sign_ind, /* i/o: next sign ind */ + UWord32 * ind /* o: MPVQ index */ +) +{ + UWord32 lead_sign_ind_add; + Word16 abs0, abs1, abs01, sptr; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("vec2mind_two_fx", sizeof(struct { + UWord32 lead_sign_ind_add; + Word16 abs0, abs1, abs01, sptr; + })); +#endif + + abs0 = abs_s(vec_in[0]); + abs1 = abs_s(vec_in[1]); + abs01 = add(abs0, abs1); + *k_val_out_ptr = abs01; move16(); + *ind = UL_deposit_l(0); + + *next_sign_ind = UL_deposit_h(SIGNBIT_SHRT_FX); + + IF (abs01 != 0) + { + sptr = 0; move16(); + *next_sign_ind = UL_deposit_l(sptr); + + test(); + IF (abs0 != 0 && abs1 != 0) + { + lead_sign_ind_add = UL_deposit_l(1); + if (vec_in[1] < 0) + { + lead_sign_ind_add = UL_deposit_l(2); + } + *ind = UL_addNsD(UL_deposit_l((UWord16)lshl(sub(abs1, 1), 1)), lead_sign_ind_add); + } + ELSE + { + IF (abs0 == 0) + { + *ind = UL_deposit_l((UWord16)sub(lshl(abs1, 1), 1)); + sptr = 1; move16(); + } + } + + if (vec_in[sptr] < 0) + { + *next_sign_ind = UL_deposit_l(1); + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +static void enc_push_sign(Word16 val, UWord32 *next_sign_ind, UWord32 *index) +{ + test(); + IF ((UL_and(*next_sign_ind, SIGNBIT_FX) == 0) && (val != 0)) + { + *index = UL_addNsD(UL_lshl(*index, 1), *next_sign_ind); + } + if (val < 0) + { + *next_sign_ind = UL_deposit_l(1); + } + if (val > 0) + { + *next_sign_ind = UL_deposit_l(0); + } +} + +static void vec2mind_fx(Word16 dim_in, /* i : dim */ + Word16 k_val_in, /* i : number of unit pulses */ + const Word16 *vec_in, /* i : PVQ pulse train */ + UWord32 * next_sign_ind, /* o : pushed leading sign */ + UWord32 * index, /* o : MPVQ index */ + UWord32 * N_MPVQ_ptr, /* o : size(N_MPVQ(dim,K_val_in))*/ + UWord32 * h_mem) /* o : offsets */ +{ + Counter pos; + Word16 mem_size_m1, k_val_acc, tmp_val; + UWord32 tmp_h; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("vec2mind_fx", sizeof(struct { + Counter pos; + Word16 mem_size_m1, k_val_acc, tmp_val; + UWord32 tmp_h; + })); +#endif + + mem_size_m1 = add(k_val_in, 1); + *next_sign_ind = UL_deposit_h(SIGNBIT_SHRT_FX); + + pos = sub(dim_in, 2); + vec2mind_two_fx(&vec_in[pos], &k_val_acc, next_sign_ind, index); + initOffsets_fx(3, h_mem, k_val_in); + + tmp_h = h_mem[k_val_acc]; move32(); + FOR (pos--; pos >= 0; pos--) + { + tmp_val = vec_in[pos]; move16(); + enc_push_sign(tmp_val, next_sign_ind, index); + + *index = UL_addNsD(*index, tmp_h); + + k_val_acc = add(k_val_acc, abs_s(tmp_val)); + + IF (pos != 0) + { + a_u_fwd_fx(h_mem, k_val_in, mem_size_m1); + } + tmp_h = UL_addNsD(h_mem[k_val_acc], 0U); + } + *N_MPVQ_ptr = UL_addNsD(1U, UL_addNsD(UL_lshr(tmp_h, 1), h_mem[mem_size_m1])); move32(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +PvqEntry_fx mpvq_index_fx( /* o : leading_sign_index, index, size, k_val */ + const Word16 *vec_in, /* i : signed pulse train */ + Word16 dim_in, /* i : dimension */ + Word16 k_val_local /* i : nb unit pulses */ +) +{ + PvqEntry_fx result; + UWord32 h_mem[1 + KMAX_FX + 1]; + UWord32 lead_sign_ind; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("mpvq_index_fx", sizeof(struct { + PvqEntry_fx result; + UWord32 h_mem[1 + KMAX_FX + 1]; + UWord32 lead_sign_ind; + })); +#endif +#ifdef WMOPS + BASOP_sub_sub_start("mpvq_index_fx"); +#endif + + ASSERT(k_val_local <= KMAX_FX); + + result.k_val = k_val_local; move16(); + result.dim = dim_in; move16(); + + vec2mind_fx(dim_in, k_val_local, vec_in, &lead_sign_ind, &result.index, &result.size, h_mem); + + result.lead_sign_ind = u_extract_l(lead_sign_ind); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + + return result; +} + diff --git a/lib_lc3plus/quantize_spec_fx.c b/lib_lc3plus/quantize_spec_fx.c new file mode 100644 index 000000000..4667cf146 --- /dev/null +++ b/lib_lc3plus/quantize_spec_fx.c @@ -0,0 +1,1167 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +# ifdef ENABLE_HR_MODE +void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word32 gain, Word16 gain_e, Word32 xq[], Word16 nt, Word16 target, + Word16 totalBits, Word16 *nBits, Word16 *nBits2, Word16 fs_idx, Word16 *lastnzout, + Word16 *codingdata, Word16 *lsbMode, Word16 mode, Word16 hrmode) +{ + + Word32 a1, b1, a1_i, b1_i; + Word16 t, lev1; + Word16 lastnz, lastnz2; + Word16 rateFlag; + Word32 nbits32, nbits232, target32; + Word16 nt_half; + Word32 c, ab_max, msb, a1_msb, b1_msb; + Word16 levmax; + Word16 s; + Word16 totBits, nbits_lsb; + Counter k, lev; + Word16 maxlevs; +# ifndef FUNCTION_quantizeSpec_func1 + Word16 tmp16; + Word32 offs32; + Counter i; +# else + Word32 ARM_params[3]; +# endif + +# ifdef DYNMEM_COUNT + Dyn_Mem_In("processQuantizeSpec_fx", sizeof(struct { + Word32 a1, b1, a1_i, b1_i, ab_max, c; + Word16 t, lev1; + Word16 lastnz, lastnz2; + Word16 rateFlag; + Word32 nbits32, nbits232; + Word16 nt_half; + Word16 msb, a1_msb, b1_msb, levmax; + Counter k, lev, i; + Word16 s; + Word16 tmp16; + Word32 offs32, target32; + Word16 totBits, nbits_lsb; + Word16 maxlevs; + })); +# endif + + assert(target >= 0); + + /* Quantization */ + gain = invFixp(gain, &gain_e); + + maxlevs = 21; + IF (hrmode) + { + s = sub(add(x_e, gain_e), 23); + s = s_min(s, 31); +# ifdef FUNCTION_quantizeSpec_func1 + ARM_params[0] = gain; + ARM_params[1] = s; + + quantizeSpec_func1_hr_ip(xq, x, nt, ARM_params); +# else + IF(s > 4) + { + s = sub(s, 4); /* Use extra bits of precision for fine calculation */ + FOR(i = 0; i < nt; i++) + { + offs32 = Mpy_32_32_lc3plus(L_shl_pos(x[i], s), gain); /* multiply */ + xq[i] = L_shr_r_pos(offs32, 4); /* Convert to Q0 with rounding */ + /* rounding is the equivalent of adding 0.5, which is the offset in hrmode */ + + move32(); + } + } + ELSE + { + FOR(i = 0; i < nt; i++) + { + offs32 = Mpy_32_32_lc3plus(x[i], gain); /* multiply */ + offs32 = L_shl(offs32, s); /* convert to 23Q8 */ + xq[i] = L_shr_r_pos(offs32, 8); /* Convert to Q0 with rounding */ + /* rounding is the equivalent of adding 0.5, which is the offset in hrmode */ + + move32(); + } + } +# endif /* FUNCTION_quantizeSpec_func1 */ + } + ELSE + { + s = sub(add(x_e, gain_e), 15); + s = s_max(s_min(s, 15), -15); +# ifdef FUNCTION_quantizeSpec_func1 + ARM_params[0] = gain; + ARM_params[1] = s; + ARM_params[2] = -4096; + quantizeSpec_func1_ip(xq, x, nt, ARM_params); +# else + FOR (i = 0; i < nt; i++) + { + offs32 = Mpy_32_32_lc3plus(L_abs(x[i]), gain); /* multiply */ + offs32 = L_shl(offs32, s); /* convert to 15Q16 */ + tmp16 = mac_r(offs32, -4096, 1); /* add offset and truncate */ + + if (x[i] < 0) + tmp16 = negate(tmp16); /* restore sign */ + + /* Normal quantization: xq[i] = x[i] / gg + sign(x[i]) * 0.375 + quant_offset is -0.125 in Q15 and round adds 0.5 in Q16. Hence + mac_r results in abs(x[i])/gain - 0.125 + 0.5 = abs(x[i])/gain + 0.375. + Due to the abs and negate combination this achieves the same result + as spec. + */ + + xq[i] = tmp16; + move16(); + } +# endif /* FUNCTION_quantizeSpec_func1 */ + } + /* Rate flag */ + rateFlag = 0; + move16(); + if (fs_idx != 5) + { + if (sub(totalBits, add(160, DEPR_i_mult(fs_idx, 160))) > 0) + { + rateFlag = 2 << NBITS_CONTEXT; + move16(); + } + } + + /* Init */ + nt_half = shr_pos(nt, 1); + c = 0; + move16(); + t = 0; + move16(); + a1_i = 0; + move16(); + b1_i = 1; + move16(); + target32 = L_shl_pos(L_deposit_l(target), SYM_BITS_Q); + nbits32 = L_negate(target32); + nbits232 = 0; + move32(); + nbits_lsb = 0; + move16(); + + if (fs_idx != 5) + { + IF (mode == 0 && sub(totalBits, add(480, DEPR_i_mult(fs_idx, 160))) >= 0) + { + mode = 1; + move16(); + } + } + + /* Find last non-zero tuple */ + lastnz = find_last_nz_pair(xq, nt); + IF (mode >= 0) + { + lastnz2 = 2; + } + ELSE + { + lastnz2 = lastnz; + } + + IF (mode < 0) + { + /* Main Loop through the 2-tuples */ + FOR (k = 0; k < lastnz; k += 2) + { + + /* Get context */ + t = add(c, rateFlag); + if (sub(k, nt_half) > 0) + { + t = add(t, 1 << NBITS_CONTEXT); + } + codingdata[0] = t; + move16(); + + /* Init current 2-tuple encoding */ + a1 = L_abs(xq[a1_i]); + b1 = L_abs(xq[b1_i]); + ab_max = L_max(a1, b1); + + IF (ab_max == 0) + { + codingdata[1] = -1; + move16(); + codingdata[2] = 0; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][0]); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (L_sub(ab_max, A_THRES) < 0) + { + codingdata[1] = 0; + move16(); + msb = L_add(a1, L_shl_pos(b1, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + c = L_add(shl_pos(s_and(c, 0xf), 4), L_add(L_add(a1, b1), 1)); + } + ELSE IF (L_sub(ab_max, 2 * A_THRES) < 0) + { + codingdata[1] = 1; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][VAL_ESC]); + nbits32 = L_add(nbits32, 2 << SYM_BITS_Q); + a1_msb = L_shr_pos_pos(a1, 1); + b1_msb = L_shr_pos_pos(b1, 1); + msb = L_add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + c = L_add(shl_pos(s_and(c, 0xf), 4), L_add(L_shl_pos(L_add(a1_msb, b1_msb), 1), 1)); + } + ELSE + { + levmax = sub(maxlevs, sub(norm_l(ab_max), 8)); + codingdata[1] = levmax; + move16(); + FOR (lev = 0; lev < levmax; lev++) + { + lev1 = s_min(lev, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][VAL_ESC]); + } + nbits32 = L_add(nbits32, L_shl_pos(L_deposit_l(levmax), SYM_BITS_Q + 1)); + a1_msb = L_shr(a1, levmax); + b1_msb = L_shr(b1, levmax); + msb = L_add(a1_msb, L_shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + lev1 = s_min(levmax, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(12, s_min(levmax, 3))); + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /* end of the 2-tuples loop */ + } + ELSE IF (mode == 0) + { + /* Main Loop through the 2-tuples */ + FOR (k = 0; k < lastnz; k += 2) + { + + /* Get context */ + t = add(c, rateFlag); + if (sub(k, nt_half) > 0) + { + t = add(t, 1 << NBITS_CONTEXT); + } + + codingdata[0] = t; + move16(); + + /* Init current 2-tuple encoding */ + a1 = L_abs(xq[a1_i]); + b1 = L_abs(xq[b1_i]); + ab_max = L_max(a1, b1); + + IF (ab_max == 0) + { + codingdata[1] = -1; + move16(); + codingdata[2] = 0; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][0]); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (L_sub(ab_max, A_THRES) < 0) + { + codingdata[1] = 0; + move16(); + msb = L_add(a1, L_shl_pos(b1, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + + c = L_add(shl_pos(s_and(c, 0xf), 4), L_add(L_add(a1, b1), 1)); + } + ELSE IF (L_sub(ab_max, 2 * A_THRES) < 0) + { + codingdata[1] = 1; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][VAL_ESC]); + nbits32 = L_add(nbits32, 2 << SYM_BITS_Q); + a1_msb = L_shr_pos_pos(a1, 1); + b1_msb = L_shr_pos_pos(b1, 1); + msb = L_add(a1_msb, L_shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + + c = add(shl_pos(s_and(c, 0xf), 4), L_add(L_shl_pos(L_add(a1_msb, b1_msb), 1), 1)); + } + ELSE + { + levmax = sub(maxlevs, sub(norm_l(ab_max), 8)); + codingdata[1] = levmax; + move16(); + FOR (lev = 0; lev < levmax; lev++) + { + lev1 = s_min(lev, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][VAL_ESC]); + } + nbits32 = L_add(nbits32, L_shl_pos(L_deposit_l(levmax), SYM_BITS_Q + 1)); + a1_msb = L_shr(a1, levmax); + b1_msb = L_shr(b1, levmax); + msb = L_add(a1_msb, L_shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + lev1 = s_min(levmax, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + + c = add(shl_pos(s_and(c, 0xf), 4), add(12, s_min(levmax, 3))); + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /* end of the 2-tuples loop */ + } + ELSE + { + /* Main Loop through the 2-tuples */ + FOR (k = 0; k < lastnz; k += 2) + { + + /* Get context */ + t = add(c, rateFlag); + + if (sub(k, nt_half) > 0) + { + t = add(t, 1 << NBITS_CONTEXT); + } + + codingdata[0] = t; + move16(); + + /* Init current 2-tuple encoding */ + a1 = L_abs(xq[a1_i]); + b1 = L_abs(xq[b1_i]); + ab_max = L_max(a1, b1); + + IF (ab_max == 0) + { + codingdata[1] = -1; + move16(); + codingdata[2] = 0; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][0]); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (L_sub(ab_max, A_THRES) < 0) + { + codingdata[1] = 0; + move16(); + msb = L_add(a1, L_shl_pos(b1, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + + c = add(shl_pos(s_and(c, 0xf), 4), add(add(a1, b1), 1)); + } + ELSE IF (L_sub(ab_max, 2 * A_THRES) < 0) + { + codingdata[1] = 1; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][VAL_ESC]); + a1_msb = L_shr_pos_pos(a1, 1); + b1_msb = L_shr_pos_pos(b1, 1); + msb = L_add(a1_msb, L_shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[1]]][msb]); + if (a1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + nbits_lsb = add(nbits_lsb, 2); + if (L_sub(a1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + if (L_sub(b1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + + c = add(shl_pos(s_and(c, 0xf), 4), add(shl_pos(add(a1_msb, b1_msb), 1), 1)); + } + ELSE + { + levmax = sub(maxlevs, sub(norm_l(ab_max), 8)); + codingdata[1] = levmax; + move16(); + FOR (lev = 0; lev < levmax; lev++) + { + lev1 = s_min(lev, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][VAL_ESC]); + } + nbits32 = L_add(nbits32, L_shl_pos(L_deposit_l(sub(levmax, 1)), SYM_BITS_Q + 1)); + a1_msb = L_shr(a1, levmax); + b1_msb = L_shr(b1, levmax); + msb = L_add(a1_msb, L_shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + lev1 = s_min(levmax, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][msb]); + a1_msb = L_shr_pos(a1, 1); + b1_msb = L_shr_pos(b1, 1); + if (a1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + nbits_lsb = add(nbits_lsb, 2); + if (L_sub(a1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + if (L_sub(b1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + + c = add(shl_pos(s_and(c, 0xf), 4), add(12, s_min(levmax, 3))); + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /* end of the 2-tuples loop */ + } + + /* Number of consumed bits */ + nbits32 = L_add(nbits32, target32); + totBits = add(extract_l(L_shr_pos_pos(L_sub(nbits32, 1), SYM_BITS_Q)), 1); + IF (mode > 0) + { + totBits = add(totBits, nbits_lsb); + } + IF (nBits != NULL) + { + *nBits = totBits; + } + IF (mode >= 0) + { + nbits232 = L_add(nbits232, target32); + *nBits2 = add(extract_l(L_shr_pos(L_sub(nbits232, 1), SYM_BITS_Q)), 1); + } + ELSE + { + *nBits2 = *nBits; + move16(); + } + IF (mode > 0) + { + *nBits2 = add(*nBits2, nbits_lsb); + } + *lastnzout = lastnz2; + + /* Truncation of high frequency coefficients */ + IF (lastnz > lastnz2) + { + basop_memset(&xq[lastnz2], 0, (lastnz - lastnz2) * sizeof(*xq)); + } + + /* Truncation of LSBs */ + test(); + IF (mode > 0 && sub(totBits, target) > 0) + { + *lsbMode = 1; + move16(); + } + ELSE + { + *lsbMode = 0; + move16(); + } + +# ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +# endif +} + +# else /* ENABLE_HR_MODE */ + +void processQuantizeSpec_fx(Word32 x[], Word16 x_e, Word16 gain, Word16 gain_e, Word16 xq[], Word16 nt, Word16 target, + Word16 totalBits, Word16 *nBits, Word16 *nBits2, Word16 fs_idx, Word16 *lastnzout, + Word16 *codingdata, Word16 *lsbMode, Word16 mode +) +{ + + Word16 a1, b1, a1_i, b1_i; + Word16 t, lev1; + Word16 lastnz, lastnz2; + Word16 rateFlag; + Word32 nbits32, nbits232, target32; + Word16 nt_half; + Word16 c, ab_max, msb, a1_msb, b1_msb, levmax; + Word16 s; + Word16 totBits, nbits_lsb; + Counter k, lev; + Word16 tmp16; + Word32 offs32; + Counter i; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processQuantizeSpec_fx", sizeof(struct { + Word16 a1, b1, a1_i, b1_i; + Word16 t, lev1; + Word16 lastnz, lastnz2; + Word16 rateFlag; + Word32 nbits32, nbits232; + Word16 nt_half; + Word16 c, ab_max, msb, a1_msb, b1_msb, levmax; + Counter k, lev, i; + Word16 s; + Word16 tmp16; + Word32 offs32, target32; + Word16 totBits, nbits_lsb; + })); +#endif + + /* Quantization */ + gain = Inv16_lc3plus(gain, &gain_e); + s = sub(add(x_e, gain_e), 15); + s = s_max(s_min(s, 15), -15); + + FOR (i = 0; i < nt; i++) + { + offs32 = Mpy_32_16_lc3plus(L_abs(x[i]), gain); /* multiply */ + offs32 = L_shl(offs32, s); /* convert to 15Q16 */ + tmp16 = extract_h(L_add(offs32, 0x00006000)); /* add offset and truncate */ + Word16 x_sign = (Word16) L_shr(x[i], 31); + xq[i] = sub(s_xor(tmp16, x_sign), x_sign); + move16(); + /* + Normal quantization: xq[i] = x[i] / gg + sign(x[i]) * 0.375 + -> 0.375 = 0x00006000 in 15Q16 + */ + } + + /* Rate flag */ + rateFlag = 0; + move16(); + if (sub(totalBits, add(160, DEPR_i_mult(fs_idx, 160))) > 0) + { + rateFlag = 2 << NBITS_CONTEXT; + move16(); + } + + /* Init */ + nt_half = shr_pos(nt, 1); + c = 0; + move16(); + t = 0; + move16(); + a1_i = 0; + move16(); + b1_i = 1; + move16(); + target32 = L_shl_pos(L_deposit_l(target), SYM_BITS_Q); + nbits32 = L_negate(target32); + nbits232 = 0; + move32(); + nbits_lsb = 0; + move16(); + IF (mode == 0 && sub(totalBits, add(480, DEPR_i_mult(fs_idx, 160))) >= 0) + { + mode = 1; + move16(); + } + + /* Find last non-zero tuple */ + lastnz = find_last_nz_pair(xq, nt); + IF (mode >= 0) + { + lastnz2 = 2; + } + ELSE + { + lastnz2 = lastnz; + } + + IF (mode < 0) + { + /* Main Loop through the 2-tuples */ + FOR (k = 0; k < lastnz; k += 2) + { + + /* Get context */ + t = add(c, rateFlag); + if (sub(k, nt_half) > 0) + { + t = add(t, 1 << NBITS_CONTEXT); + } + codingdata[0] = t; + move16(); + + /* Init current 2-tuple encoding */ + a1 = abs_s(xq[a1_i]); + b1 = abs_s(xq[b1_i]); + ab_max = s_max(a1, b1); + + IF (ab_max == 0) + { + codingdata[1] = -1; + move16(); + codingdata[2] = 0; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][0]); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (sub(ab_max, A_THRES) < 0) + { + codingdata[1] = 0; + move16(); + msb = add(a1, shl_pos(b1, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(add(a1, b1), 1)); + } + ELSE IF (sub(ab_max, 2 * A_THRES) < 0) + { + codingdata[1] = 1; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][VAL_ESC]); + nbits32 = L_add(nbits32, 2 << SYM_BITS_Q); + a1_msb = shr_pos_pos(a1, 1); + b1_msb = shr_pos_pos(b1, 1); + msb = add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(shl_pos(add(a1_msb, b1_msb), 1), 1)); + } + ELSE + { + levmax = sub(13, norm_s(ab_max)); + codingdata[1] = levmax; + move16(); + FOR (lev = 0; lev < levmax; lev++) + { + lev1 = s_min(lev, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][VAL_ESC]); + } + nbits32 = L_add(nbits32, L_shl_pos(L_deposit_l(levmax), SYM_BITS_Q + 1)); + a1_msb = shr(a1, levmax); + b1_msb = shr(b1, levmax); + msb = add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + lev1 = s_min(levmax, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(12, s_min(levmax, 3))); + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /* end of the 2-tuples loop */ + } + ELSE IF (mode == 0) + { + /* Main Loop through the 2-tuples */ + FOR (k = 0; k < lastnz; k += 2) + { + + /* Get context */ + t = add(c, rateFlag); + if (sub(k, nt_half) > 0) + { + t = add(t, 1 << NBITS_CONTEXT); + } + codingdata[0] = t; + move16(); + + /* Init current 2-tuple encoding */ + a1 = abs_s(xq[a1_i]); + b1 = abs_s(xq[b1_i]); + ab_max = s_max(a1, b1); + + IF (ab_max == 0) + { + codingdata[1] = -1; + move16(); + codingdata[2] = 0; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][0]); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (sub(ab_max, A_THRES) < 0) + { + codingdata[1] = 0; + move16(); + msb = add(a1, shl_pos(b1, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(add(a1, b1), 1)); + } + ELSE IF (sub(ab_max, 2 * A_THRES) < 0) + { + codingdata[1] = 1; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][VAL_ESC]); + nbits32 = L_add(nbits32, 2 << SYM_BITS_Q); + a1_msb = shr_pos_pos(a1, 1); + b1_msb = shr_pos_pos(b1, 1); + msb = add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(shl_pos(add(a1_msb, b1_msb), 1), 1)); + } + ELSE + { + levmax = sub(13, norm_s(ab_max)); + codingdata[1] = levmax; + move16(); + FOR (lev = 0; lev < levmax; lev++) + { + lev1 = s_min(lev, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][VAL_ESC]); + } + nbits32 = L_add(nbits32, L_shl_pos(L_deposit_l(levmax), SYM_BITS_Q + 1)); + a1_msb = shr(a1, levmax); + b1_msb = shr(b1, levmax); + msb = add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + lev1 = s_min(levmax, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(12, s_min(levmax, 3))); + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /* end of the 2-tuples loop */ + } + ELSE + { + /* Main Loop through the 2-tuples */ + FOR (k = 0; k < lastnz; k += 2) + { + + /* Get context */ + t = add(c, rateFlag); + if (sub(k, nt_half) > 0) + { + t = add(t, 1 << NBITS_CONTEXT); + } + codingdata[0] = t; + move16(); + + /* Init current 2-tuple encoding */ + a1 = abs_s(xq[a1_i]); + b1 = abs_s(xq[b1_i]); + ab_max = s_max(a1, b1); + + IF (ab_max == 0) + { + codingdata[1] = -1; + move16(); + codingdata[2] = 0; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][0]); + c = add(shl_pos(s_and(c, 0xf), 4), 1); + } + ELSE IF (sub(ab_max, A_THRES) < 0) + { + codingdata[1] = 0; + move16(); + msb = add(a1, shl_pos(b1, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][msb]); + if (a1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1 != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(add(a1, b1), 1)); + } + ELSE IF (sub(ab_max, 2 * A_THRES) < 0) + { + codingdata[1] = 1; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t]][VAL_ESC]); + a1_msb = shr_pos_pos(a1, 1); + b1_msb = shr_pos_pos(b1, 1); + msb = add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[1]]][msb]); + if (a1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + nbits_lsb = add(nbits_lsb, 2); + if (sub(a1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + if (sub(b1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(shl_pos(add(a1_msb, b1_msb), 1), 1)); + } + ELSE + { + levmax = sub(13, norm_s(ab_max)); + codingdata[1] = levmax; + move16(); + FOR (lev = 0; lev < levmax; lev++) + { + lev1 = s_min(lev, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][VAL_ESC]); + } + nbits32 = L_add(nbits32, L_shl_pos(L_deposit_l(sub(levmax, 1)), SYM_BITS_Q + 1)); + a1_msb = shr(a1, levmax); + b1_msb = shr(b1, levmax); + msb = add(a1_msb, shl_pos(b1_msb, A_THRES_SHIFT)); + codingdata[2] = msb; + move16(); + lev1 = s_min(levmax, 3); + nbits32 = L_add(nbits32, ari_spec_bits[ari_spec_lookup[t + Tab_esc_nb[lev1]]][msb]); + a1_msb = shr_pos(a1, 1); + b1_msb = shr_pos(b1, 1); + if (a1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + if (b1_msb != 0) + { + nbits32 = L_add(nbits32, 1 << SYM_BITS_Q); + } + nbits_lsb = add(nbits_lsb, 2); + if (sub(a1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + if (sub(b1, 1) == 0) + { + nbits_lsb = add(nbits_lsb, 1); + } + if (nbits32 <= 0) + { + lastnz2 = add(k, 2); + } + if (nbits32 <= 0) + { + nbits232 = nbits32; + move32(); + } + c = add(shl_pos(s_and(c, 0xf), 4), add(12, s_min(levmax, 3))); + } + + a1_i += 2; + b1_i += 2; + codingdata += 3; + + } /* end of the 2-tuples loop */ + } + + /* Number of consumed bits */ + nbits32 = L_add(nbits32, target32); + totBits = add(extract_l(L_shr_pos_pos(L_sub(nbits32, 1), SYM_BITS_Q)), 1); + IF (mode > 0) + { + totBits = add(totBits, nbits_lsb); + } + IF (nBits != NULL) + { + *nBits = totBits; + } + IF (mode >= 0) + { + nbits232 = L_add(nbits232, target32); + *nBits2 = add(extract_l(L_shr_pos(L_sub(nbits232, 1), SYM_BITS_Q)), 1); + } + ELSE + { + *nBits2 = *nBits; + move16(); + } + IF (mode > 0) + { + *nBits2 = add(*nBits2, nbits_lsb); + } + *lastnzout = lastnz2; + + /* Truncation of high frequency coefficients */ + IF (lastnz > lastnz2) + { + basop_memset(&xq[lastnz2], 0, (lastnz - lastnz2) * sizeof(*xq)); + } + + /* Truncation of LSBs */ + test(); + IF (mode > 0 && sub(totBits, target) > 0) + { + *lsbMode = 1; + move16(); + } + ELSE + { + *lsbMode = 0; + move16(); + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +# endif /* ENABLE_HR_MODE */ diff --git a/lib_lc3plus/reorder_bitstream_fx.c b/lib_lc3plus/reorder_bitstream_fx.c new file mode 100644 index 000000000..281eef325 --- /dev/null +++ b/lib_lc3plus/reorder_bitstream_fx.c @@ -0,0 +1,56 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "defines.h" + +#include "constants.h" +#include "functions.h" + + +void processReorderBitstream_fx(UWord8 *bytes, Word16 n_pccw, Word16 n_pc, Word16 b_left, Word8 *scratchBuffer) +{ + Word16 block_bytes; + UWord8 * bytes_tmp; + +#ifdef DYNMEM_COUNT + struct _dynmem + { + Word16 block_bits, block_bytes; + UWord8 * bytes_tmp; + }; + Dyn_Mem_In("processReorderBitstream_fx", sizeof(struct _dynmem)); +#endif + + bytes_tmp = (UWord8 *)scratchAlign(scratchBuffer, 0); /* Size = LC3PLUS_MAX_BYTES */ + + if (n_pccw == 0) + { +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + return; + } + + assert(b_left >= 0); + + /* set block size in bits and full bytes */ + block_bytes = shr_sat(add(n_pc, 1), 1); + + /* rearrange bitstream */ + basop_memmove(&bytes_tmp[0], &bytes[b_left], block_bytes * sizeof(UWord8)); + basop_memmove(&bytes_tmp[block_bytes], &bytes[0], b_left * sizeof(UWord8)); + + basop_memmove(&bytes[0], &bytes_tmp[0], add(block_bytes, b_left) * sizeof(UWord8)); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + + diff --git a/lib_lc3plus/resamp12k8_fx.c b/lib_lc3plus/resamp12k8_fx.c new file mode 100644 index 000000000..a54f6bc29 --- /dev/null +++ b/lib_lc3plus/resamp12k8_fx.c @@ -0,0 +1,121 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void process_resamp12k8_fx(Word16 x[], Word16 x_len, Word16 mem_in[], Word16 mem_in_len, Word32 mem_50[], + Word16 mem_out[], Word16 mem_out_len, Word16 y[], Word16 *y_len, Word16 fs_idx, + Word16 frame_dms, Word8 *scratchBuffer + , Word16 bps + ) +{ + Dyn_Mem_Deluxe_In( + Word16 * buf; + Word16 index_int, index_frac, len_12k8; + Word16 resamp_upfac, resamp_off_int, resamp_off_frac, resamp_delay; + const Word16 *resamp_filt; + const Word16 *filt_coeff; + Word16 * filt_input; + Word32 filt_output, mem_50_0, mem_50_1; + Counter n, m; + Word32 L_tmp; + ); + + buf = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * (MAX_LEN + MAX_LEN / 8) bytes */ + + /* resamp parameters : {upsample-factor, 120 / upsample-factor, down_sample_int_part, down_sample_frac_part } + upsample is to 384 kHz. upsample-facor = 192000 / samp-freq + Fractional downsample parameters are calculated from : downsample samp-freq to 128000 + At 48000 sampling frequency: + upsample-factor = 192000 / 48000 = 4 + 120 / upsample-factor = 120 / 4 = 30 + downsample-ratio = 48000 / 12800 = 3.75 + down_sample_int_part = 3 + down_sample_frac_part = int(0.75 * upsample-factor ) = 0.75 * 4 = 3 + */ + resamp_upfac = resamp_params[fs_idx][0]; move16(); + resamp_delay = resamp_params[fs_idx][1]; move16(); + resamp_off_int = resamp_params[fs_idx][2]; move16(); + resamp_off_frac = resamp_params[fs_idx][3]; move16(); + resamp_filt = resamp_filts[fs_idx]; move16(); + + len_12k8 = LEN_12K8 / 4 * (frame_dms / 25); move16(); + *y_len = len_12k8; move16(); + + /* Init Input Buffer */ + basop_memmove(buf, mem_in, mem_in_len * sizeof(Word16)); + basop_memmove(&buf[mem_in_len], x, x_len * sizeof(Word16)); + basop_memmove(mem_in, &buf[x_len], mem_in_len * sizeof(Word16)); + + /* Init Input Indices */ + index_int = 1; move16(); + index_frac = 0; move16(); + + /* Resampling */ + FOR (n = 0; n < len_12k8; n++) + { + /* Init Filtering */ + filt_input = &buf[index_int]; + filt_coeff = &resamp_filt[index_frac * resamp_delay * 2]; + +/* Perform Filtering */ + filt_output = L_mult0(*filt_input, *filt_coeff); + FOR (m = 1; m < resamp_delay * 2; m++) + { + filt_coeff++; + filt_input++; + if (*filt_coeff) + { + filt_output = L_mac0(filt_output, *filt_input, *filt_coeff); + } + } + y[n] = round_fx(filt_output); move16(); + + /* Update Input Indices */ + index_int = add(index_int, resamp_off_int); + index_frac = add(index_frac, resamp_off_frac); + IF (sub(resamp_upfac, index_frac) <= 0) + { + index_int = add(index_int, 1); + index_frac = sub(index_frac, resamp_upfac); + } + } + + /* High Pass Filtering (-3dB at 50Hz) */ + mem_50_0 = mem_50[0]; move32(); + mem_50_1 = mem_50[1]; move32(); + + FOR (n = 0; n < len_12k8; n++) + { + filt_output = L_mac0_sat(mem_50_0, highpass50_filt_num[0], y[n]); + L_tmp = L_mac0(Mpy_32_16_lc3plus(filt_output, highpass50_filt_den[0]), highpass50_filt_num[1], y[n]); + + IF (sub(bps, 24) == 0) + { + mem_50_0 = L_shl_sat(L_add_sat(L_shr_pos(mem_50_1,1), L_tmp), 1); + } ELSE + { + mem_50_0 = L_add_sat(mem_50_1, L_shl_sat(L_tmp, 1)); + } + + mem_50_1 = L_mac0(Mpy_32_16_lc3plus(filt_output, highpass50_filt_den[1]), highpass50_filt_num[2], y[n]); + y[n] = round_fx_sat(filt_output); move16(); + } + mem_50[0] = mem_50_0; move32(); + mem_50[1] = mem_50_1; move32(); + +/* Output Buffer */ + basop_memmove(buf, mem_out, mem_out_len * sizeof(Word16)); + basop_memmove(&buf[mem_out_len], y, len_12k8 * sizeof(Word16)); + basop_memmove(y, buf, (*y_len + 1) * sizeof(Word16)); + basop_memmove(mem_out, &buf[len_12k8], mem_out_len * sizeof(Word16)); + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/residual_coding_fx.c b/lib_lc3plus/residual_coding_fx.c new file mode 100644 index 000000000..2cb6c791f --- /dev/null +++ b/lib_lc3plus/residual_coding_fx.c @@ -0,0 +1,238 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +#ifdef ENABLE_HR_MODE + +void processResidualCoding_fx(Word16 x_e, Word32 x[], + Word32 xq[], Word32 gain, + Word16 gain_e, Word16 L_spec, + Word16 targetBits, Word16 nBits, UWord8 *resBits, Word16 *numResBits + , Word16 hrmode +) +{ + + Counter i; + Word16 s, n, m; + Word32 L_tmp; + Word16 iter = 0; + Counter idx; + Word16 N_nz = 0; + Word16 n1, n2; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processResidualCoding_fx", sizeof(struct { + Counter i; + Word16 s, n, m; + Word32 L_tmp; + Word16 iter; + Counter idx; + Word16 N_nz; + Word16 *nz_idx; + Word16 n1, n2; + })); +#endif + + n = 0; + move16(); + + IF (hrmode) + { + m = add(sub(targetBits, nBits), 14); + assert(m <= (MAX_RESBITS_LEN << RESBITS_PACK_SHIFT)); + } + ELSE + { + m = add(sub(targetBits, nBits), 4); + if (m > L_spec) + { + m = L_spec; + } + } + + basop_memset(resBits, 0, sizeof(*resBits)*((m + RESBITS_PACK_MASK) >> RESBITS_PACK_SHIFT)); + + s = sub(add(15, gain_e), x_e); + + IF(hrmode) + { + /* + x = xval * 2^(31 - x_e) + gain = gainval * 2^(15 - gain_e) + + To bring gain to the same q of x : + + gain (in_Qx_e) = gain * 2^(16 + gain_e - x_e) + + gain*offset (in Qx_e) = gain (in_Qx_e) * 0.25 = gain (in_Qx_e) / 4 = gain * 2^(16 - 2 + gain_e - x_e) + */ + Word16 shift_val; + shift_val = sub(sub(gain_e, x_e), 2); + + Word32 gain_offset; + + IF (shift_val <= -32) + gain_offset = 0; + ELSE + { + gain_offset = L_shl_sat(gain, shift_val); + } + + Word16 exit_iter = 0; + + Word16 nz_idx[MAX_LEN]; + + /* enumerate non-zero coefficients */ + FOR (i = 0; i < L_spec; i++) + { + IF (xq[i]) + { + nz_idx[N_nz] = i; move16(); + N_nz = add(N_nz, 1); + } + } + + s = sub(31, sub(x_e, gain_e)); + FOR (iter = 0; iter < EXT_RES_ITER_MAX; iter++) + { + FOR (i = 0; i < N_nz; i++) + { + idx = nz_idx[i]; + + L_tmp = L_sub(x[idx], Mpy_32_32_lc3plus(L_shl(xq[idx], s), gain)); + + IF (L_tmp >= 0) + { + n1 = shr(n, RESBITS_PACK_SHIFT); + n2 = s_and(n, RESBITS_PACK_MASK); + resBits[n1] = (UWord8)s_or(resBits[n1], shl(1, n2)); + move16(); + x[idx] = L_sub(x[idx], gain_offset); + move16(); + } + ELSE + { + move16(); + x[idx] = L_add(x[idx], gain_offset); + move16(); + } + n = add(n, 1); + IF (sub(n, m) == 0) + { + exit_iter = 1; + BREAK; + } + } + gain_offset = L_shr(gain_offset, 1); /* offset *= 0.5 */ + + IF (exit_iter) + { + BREAK; + } + } + } + ELSE + { + s = add(s, 16); + gain = round_fx(gain); + + FOR (i = 0; i < L_spec; i++) + { + IF (xq[i] != 0) + { + L_tmp = L_sub(x[i], Mpy_32_16_lc3plus(L_shl(xq[i], s), gain)); + if (L_tmp >= 0) + { + n1 = shr(n, RESBITS_PACK_SHIFT); + n2 = s_and(n, RESBITS_PACK_MASK); + resBits[n1] = (UWord8) s_or(resBits[n1], shl(1, n2)); + move16(); + } + n = add(n, 1); + IF (sub(n, m) == 0) + { + BREAK; + } + } + } + } + *numResBits = n; + move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +#else + +void processResidualCoding_fx(Word16 x_e, Word32 x[], + Word16 xq[], + Word16 gain, Word16 gain_e, Word16 L_spec, + Word16 targetBits, Word16 nBits, UWord8 *resBits, Word16 *numResBits +) +{ + + Counter i; + Word16 s, n, m; + Word32 L_tmp; +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processResidualCoding_fx", sizeof(struct { + Counter i; + Word16 s, n, m; + Word32 L_tmp; + })); +#endif + + n = 0; + move16(); + { + m = add(sub(targetBits, nBits), 4); + if (m > L_spec) + { + m = L_spec; + } + } + + + s = sub(add(15, gain_e), x_e); + { + FOR (i = 0; i < L_spec; i++) + { + IF (xq[i] != 0) + { + L_tmp = L_sub(x[i], L_shl(L_mult(xq[i], gain), s)); + if (L_tmp < 0) + { + resBits[n] = 0; + move16(); + } + if (L_tmp >= 0) + { + resBits[n] = 1; + move16(); + } + n = add(n, 1); + IF (sub(n, m) == 0) + { + BREAK; + } + } + } + } + *numResBits = n; + move16(); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +#endif diff --git a/lib_lc3plus/residual_decoding_fx.c b/lib_lc3plus/residual_decoding_fx.c new file mode 100644 index 000000000..686398cdd --- /dev/null +++ b/lib_lc3plus/residual_decoding_fx.c @@ -0,0 +1,207 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +#ifdef ENABLE_HR_MODE /* HRMODE enables packing of residual bits */ + +void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 prm[], Word16 resQBits +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +) +{ + + Counter i; + Word32 fac_m, fac_p; + Word16 s, bits; + Word32 tmp; + Counter idx; + Word16 N_nz = 0; + Word16 iter; + Word32 fac_hr; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processResidualDecoding_fx", sizeof(struct { + Counter i; + Word32 fac_m, fac_p; + Word16 s, bits; + Word32 tmp; + Counter idx; + Word16 N_nz; + Word16 *nz_idx; + Word16 iter; + })); +#endif + + tmp = 0; + s = sub(x_e, 1); + s = s_min(s, 31); + + IF (hrmode) + { + fac_hr = L_shr(0x10000000, s); /* 0.25 in 1Q30 */ + } + ELSE + { + fac_m = L_shr(0xC000000, s); /* 0.1875 in 1Q30 */ + fac_p = L_shr(0x14000000, s); /* 0.3125 in 1Q30 */ + } + + bits = 0; + move16(); + + Word16 nz_idx[MAX_LEN]; + + IF (hrmode) + { + FOR (i = 0; i < L_spec; i++) + { + IF (x[i]) + { + nz_idx[N_nz] = i; move16(); + N_nz = add(N_nz, 1); + } + } + FOR (iter = 0; iter < EXT_RES_ITER_MAX; iter++) + { + IF (sub(bits, resQBits) >= 0) + { + BREAK; + } + FOR (i = 0; i < N_nz; i++) + { + idx = nz_idx[i]; move16(); + + IF (sub(bits, resQBits) >= 0) + { + BREAK; + } + + IF (! (s_and(prm[shr(bits, RESBITS_PACK_SHIFT)], shl(1, s_and(bits, RESBITS_PACK_MASK))))) + { + tmp = L_sub_sat(x[idx], fac_hr); + } + ELSE + { + tmp = L_add_sat(x[idx], fac_hr); + } + x[idx] = tmp; + move32(); + bits = add(bits, 1); + } + fac_hr = L_shr(fac_hr, 1); + } + } + ELSE + { + FOR (i = 0; i < L_spec; i++) + { + IF (sub(bits, resQBits) >= 0) + { + BREAK; + } + + IF (x[i] != 0) + { + IF (! (s_and(prm[shr(bits, RESBITS_PACK_SHIFT)], shl(1, s_and(bits, RESBITS_PACK_MASK))))) + { + if (x[i] > 0) + tmp = L_sub(x[i], fac_m); + if (x[i] < 0) + tmp = L_sub(x[i], fac_p); + } + ELSE + { + if (x[i] > 0) + tmp = L_add(x[i], fac_p); + if (x[i] < 0) + tmp = L_add(x[i], fac_m); + } + x[i] = tmp; + move32(); + bits = add(bits, 1); + } + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +#else + +void processResidualDecoding_fx(Word32 x[], Word16 x_e, Word16 L_spec, UWord8 prm[], Word16 resQBits +) +{ + + Counter i; + Word32 fac_m, fac_p; + Word16 s, bits; + Word32 tmp; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processResidualDecoding_fx", sizeof(struct { + Counter i; + Word32 fac_m, fac_p; + Word16 s, bits; + Word32 tmp; + })); +#endif + + tmp = 0; + s = sub(x_e, 1); + s = s_min(s, 31); + + { + fac_m = L_shr(0xC000000, s); /* 0.1875 in 1Q30 */ + fac_p = L_shr(0x14000000, s); /* 0.3125 in 1Q30 */ + } + + bits = 0; + move16(); + + { + FOR (i = 0; i < L_spec; i++) + { + IF (sub(bits, resQBits) >= 0) + { + BREAK; + } + + IF (x[i] != 0) + { + IF (prm[bits] == 0) + { + if (x[i] > 0) + tmp = L_sub(x[i], fac_m); + if (x[i] < 0) + tmp = L_sub(x[i], fac_p); + } + ELSE + { + if (x[i] > 0) + tmp = L_add(x[i], fac_p); + if (x[i] < 0) + tmp = L_add(x[i], fac_m); + } + x[i] = tmp; + move32(); + bits = add(bits, 1); + } + } + } + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +#endif diff --git a/lib_lc3plus/rom_basop_util.c b/lib_lc3plus/rom_basop_util.c new file mode 100644 index 000000000..e37b4bfad --- /dev/null +++ b/lib_lc3plus/rom_basop_util.c @@ -0,0 +1,2904 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "rom_basop_util.h" +#include "basop_util_lc3plus.h" +#include "functions.h" + + +/* clang-format off */ +# ifdef ENABLE_HR_MODE +# define STC(x) (x) +# define WTC(x) (x) +# define STCP(a, b) {{STC(a), STC(b)}} +# define WTCP(a, b) {{WTC(a), WTC(b)}} +# else +# define STC(x) WORD322WORD16(x) +# define WTC(x) WORD322WORD16(x) +# define STCP(a, b) {{STC(a), STC(b)}} +# define WTCP(a, b) {{WTC(a), WTC(b)}} +# endif +/* clang-format on */ + +/** + * \brief Lookup-Table for binary logarithm + */ +RAM_ALIGN const Word16 ldCoeff_lc3plus[7] = {-32768, -16384, -10923, -8192, -6554, -5461, -4681}; + +/** + \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_lc3plus[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_lc3plus[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_lc3plus[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_lc3plus[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_lc3plus[32] = { + /* Q21 */ + 0x59CF, 0x5875, 0x572B, 0x55EE, 0x54BF, 0x539C, 0x5284, 0x5177, 0x5074, 0x4F7A, 0x4E89, + 0x4DA1, 0x4CC0, 0x4BE7, 0x4B15, 0x4A4A, 0x4985, 0x48C6, 0x480C, 0x4758, 0x46AA, 0x4600, + 0x455B, 0x44BA, 0x441D, 0x4385, 0x42F1, 0x4260, 0x41D3, 0x414A, 0x40C3, 0x4040, +}; + +const Word32 ISqrtTable_lc3plus[32] = { + /* 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_lc3plus[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_lc3plus[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, +}; + +#ifdef ENABLE_HR_MODE +const Word16 InvIntTable[74] = { + 32767, 32767, 16384, 10923, 8192, 6554, 5461, 4681, 4096, 3641, 3277, 2979, 2731, 2521, 2341, + 2185, 2048, 1928, 1820, 1725, 1638, 1560, 1489, 1425, 1365, 1311, 1260, 1214, 1170, 1130, + 1092, 1057, 1024, 993, 964, 936, 910, 886, 862, 840, 819, 799, 780, 762, 745, + 728, 712, 697, 683, 669, 655, 643, 630, 618, 607, 596, 585, 575, 565, 555, + 546, 537, 529, 520, 512, 504, 496, 489, 482, 475, 468, 462, 455, 449 +}; +#else +const Word16 InvIntTable[32] = { + 0x7FFF, 0x7FFF, 0x4000, 0x2AAB, 0x2000, 0x199A, 0x1555, 0x1249, 0x1000, 0x0E39, 0x0CCD, + 0x0BA3, 0x0AAB, 0x09D9, 0x0925, 0x0889, 0x0800, 0x0788, 0x071C, 0x06BD, 0x0666, 0x0618, + 0x05D1, 0x0591, 0x0555, 0x051F, 0x04EC, 0x04BE, 0x0492, 0x046A, 0x0444, 0x0421, +}; +#endif + +const Word16 InvDiffTable_lc3plus[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, +}; + +/* + Sine tables + */ +# ifdef ENABLE_HR_MODE +const PWord32 SineTable480[] = { +# else +const PWord16 SineTable480[] = { +# endif + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd315, 0x006b3b9b), STCP(0x7fff4c54, 0x00d676eb), + STCP(0x7ffe6bbf, 0x0141b1a5), STCP(0x7ffd3154, 0x01aceb7c), STCP(0x7ffb9d15, 0x02182427), + STCP(0x7ff9af04, 0x02835b5a), STCP(0x7ff76721, 0x02ee90c8), STCP(0x7ff4c56f, 0x0359c428), + STCP(0x7ff1c9ef, 0x03c4f52f), STCP(0x7fee74a2, 0x0430238f), STCP(0x7feac58d, 0x049b4f00), + STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fe25a0f, 0x05719be2), STCP(0x7fdd9dad, 0x05dcbcbe), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd317b4, 0x06b2f1d2), STCP(0x7fcd4e24, 0x071e0575), + STCP(0x7fc72ae2, 0x07891418), STCP(0x7fc0adf2, 0x07f41d72), STCP(0x7fb9d759, 0x085f2137), + STCP(0x7fb2a71b, 0x08ca1f1b), STCP(0x7fab1d3d, 0x093516d4), STCP(0x7fa339c5, 0x09a00817), + STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f92661d, 0x0a75d60e), STCP(0x7f8975f9, 0x0ae0b22c), + STCP(0x7f802c52, 0x0b4b86a8), STCP(0x7f76892f, 0x0bb65336), STCP(0x7f6c8c96, 0x0c21178c), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f578721, 0x0cf68662), STCP(0x7f4c7e54, 0x0d61304e), + STCP(0x7f411c2f, 0x0dcbd0d5), STCP(0x7f3560b9, 0x0e3667ad), STCP(0x7f294bfd, 0x0ea0f48c), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7f1016ce, 0x0f75ef33), STCP(0x7f02f66f, 0x0fe05c64), + STCP(0x7ef57cea, 0x104abe71), STCP(0x7ee7aa4c, 0x10b5150f), STCP(0x7ed97e9c, 0x111f5ff4), + STCP(0x7ecaf9e5, 0x11899ed3), STCP(0x7ebc1c31, 0x11f3d164), STCP(0x7eace58a, 0x125df75b), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8d6d91, 0x13321c53), STCP(0x7e7d2c54, 0x139c1abf), + STCP(0x7e6c9251, 0x14060b68), STCP(0x7e5b9f93, 0x146fee03), STCP(0x7e4a5426, 0x14d9c245), + STCP(0x7e38b017, 0x154387e6), STCP(0x7e26b371, 0x15ad3e9a), STCP(0x7e145e42, 0x1616e618), + STCP(0x7e01b096, 0x16807e15), STCP(0x7deeaa7a, 0x16ea0646), STCP(0x7ddb4bfc, 0x17537e63), + STCP(0x7dc79529, 0x17bce621), STCP(0x7db3860f, 0x18263d36), STCP(0x7d9f1ebd, 0x188f8357), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d7547a7, 0x1961db9b), STCP(0x7d5fd801, 0x19caed29), + STCP(0x7d4a105d, 0x1a33ec9c), STCP(0x7d33f0ca, 0x1a9cd9ac), STCP(0x7d1d7958, 0x1b05b40f), + STCP(0x7d06aa16, 0x1b6e7b7a), STCP(0x7cef8315, 0x1bd72fa4), STCP(0x7cd80464, 0x1c3fd045), + STCP(0x7cc02e15, 0x1ca85d12), STCP(0x7ca80038, 0x1d10d5c2), STCP(0x7c8f7ade, 0x1d793a0b), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7c5d69f7, 0x1e49c447), STCP(0x7c43de8e, 0x1eb1e9a7), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c0fc22a, 0x1f81f37c), STCP(0x7bf53153, 0x1fe9d75f), + STCP(0x7bda497d, 0x2051a4dd), STCP(0x7bbf0aba, 0x20b95bac), STCP(0x7ba3751d, 0x2120fb83), + STCP(0x7b8788ba, 0x2188841a), STCP(0x7b6b45a5, 0x21eff528), STCP(0x7b4eabf1, 0x22574e65), + STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7b1474fd, 0x2325b847), STCP(0x7af6d7e6, 0x238cc85d), + STCP(0x7ad8e482, 0x23f3bf7e), STCP(0x7aba9ae6, 0x245a9d65), STCP(0x7a9bfb27, 0x24c161c7), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5db997, 0x258e9ce0), STCP(0x7a3e17f2, 0x25f51307), + STCP(0x7a1e2082, 0x265b6e8a), STCP(0x79fdd35c, 0x26c1af22), STCP(0x79dd3098, 0x2727d486), + STCP(0x79bc384d, 0x278dde6e), STCP(0x799aea92, 0x27f3cc94), STCP(0x7979477d, 0x28599eb0), + STCP(0x79574f28, 0x28bf547b), STCP(0x793501a9, 0x2924edac), STCP(0x79125f19, 0x298a69fc), + STCP(0x78ef678f, 0x29efc925), STCP(0x78cc1b26, 0x2a550adf), STCP(0x78a879f4, 0x2aba2ee4), + STCP(0x78848414, 0x2b1f34eb), STCP(0x7860399e, 0x2b841caf), STCP(0x783b9aad, 0x2be8e5e8), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77f15fbc, 0x2cb21ba0), STCP(0x77cbc3f2, 0x2d168792), + STCP(0x77a5d413, 0x2d7ad3de), STCP(0x777f903c, 0x2ddf0040), STCP(0x7758f886, 0x2e430c6f), + STCP(0x77320d0d, 0x2ea6f827), STCP(0x770acdec, 0x2f0ac320), STCP(0x76e33b3f, 0x2f6e6d16), + STCP(0x76bb5521, 0x2fd1f5c1), STCP(0x76931bae, 0x30355cdd), STCP(0x766a8f04, 0x3098a223), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x76187c77, 0x315ec617), STCP(0x75eef6ce, 0x31c1a43b), + STCP(0x75c51e61, 0x32245f72), STCP(0x759af34c, 0x3286f779), STCP(0x757075ac, 0x32e96c09), + STCP(0x7545a5a0, 0x334bbcde), STCP(0x751a8346, 0x33ade9b3), STCP(0x74ef0ebc, 0x340ff242), + STCP(0x74c34820, 0x3471d647), STCP(0x74972f92, 0x34d3957e), STCP(0x746ac52f, 0x35352fa1), + STCP(0x743e0918, 0x3596a46c), STCP(0x7410fb6b, 0x35f7f39c), STCP(0x73e39c49, 0x36591cea), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x7387ea23, 0x371afcd5), STCP(0x73599760, 0x377bb2e9), + STCP(0x732af3a7, 0x37dc420c), STCP(0x72fbff1b, 0x383ca9fb), STCP(0x72ccb9db, 0x389cea72), + STCP(0x729d2409, 0x38fd032d), STCP(0x726d3dc6, 0x395cf3e9), STCP(0x723d0734, 0x39bcbc63), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x71dba9ab, 0x3a7bd382), STCP(0x71aa82f7, 0x3adb21a1), + STCP(0x71790c7e, 0x3b3a4672), STCP(0x71474660, 0x3b9941b1), STCP(0x711530c2, 0x3bf8131c), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b01790, 0x3cb5376b), STCP(0x707d1443, 0x3d1389cb), + STCP(0x7049c203, 0x3d71b14d), STCP(0x701620f5, 0x3dcfadb0), STCP(0x6fe2313c, 0x3e2d7eb1), + STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6f79665b, 0x3ee89d86), STCP(0x6f448b7e, 0x3f45ead8), + STCP(0x6f0f6289, 0x3fa30bc1), STCP(0x6ed9eba1, 0x40000000), STCP(0x6ea426ed, 0x405cc754), + STCP(0x6e6e1492, 0x40b9617d), STCP(0x6e37b4b6, 0x4115ce38), STCP(0x6e010780, 0x41720d46), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d92c59b, 0x422a0154), STCP(0x6d5b313b, 0x4285b5d4), + STCP(0x6d23501b, 0x42e13ba4), STCP(0x6ceb2261, 0x433c9283), STCP(0x6cb2a837, 0x4397ba32), + STCP(0x6c79e1c2, 0x43f2b271), STCP(0x6c40cf2c, 0x444d7aff), STCP(0x6c07709b, 0x44a8139e), + STCP(0x6bcdc639, 0x45027c0c), STCP(0x6b93d02e, 0x455cb40c), STCP(0x6b598ea3, 0x45b6bb5e), + STCP(0x6b1f01c0, 0x461091c2), STCP(0x6ae429ae, 0x466a36f9), STCP(0x6aa90697, 0x46c3aac5), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a31e000, 0x4775fd1f), STCP(0x69f5dcd3, 0x47cedb31), + STCP(0x69b98f48, 0x482786dc), STCP(0x697cf78a, 0x487fffe4), STCP(0x694015c3, 0x48d84609), + STCP(0x6902ea1d, 0x4930590f), STCP(0x68c574c4, 0x498838b6), STCP(0x6887b5e2, 0x49dfe4c2), + STCP(0x6849ada3, 0x4a375cf5), STCP(0x680b5c33, 0x4a8ea111), STCP(0x67ccc1be, 0x4ae5b0da), + STCP(0x678dde6e, 0x4b3c8c12), STCP(0x674eb271, 0x4b93327c), STCP(0x670f3df3, 0x4be9a3db), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x668f7c25, 0x4c95e688), STCP(0x664f2f2e, 0x4cebb75c), + STCP(0x660e9a6a, 0x4d415234), STCP(0x65cdbe05, 0x4d96b6d3), STCP(0x658c9a2d, 0x4debe4fe), + STCP(0x654b2f10, 0x4e40dc79), STCP(0x65097cdb, 0x4e959d08), STCP(0x64c783bd, 0x4eea2670), + STCP(0x648543e4, 0x4f3e7875), STCP(0x6442bd7e, 0x4f9292dc), STCP(0x63fff0ba, 0x4fe6756a), + STCP(0x63bcddc7, 0x503a1fe5), STCP(0x637984d4, 0x508d9211), STCP(0x6335e611, 0x50e0cbb4), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62add7d6, 0x51869476), STCP(0x626968be, 0x51d92321), + STCP(0x6224b495, 0x522b7859), STCP(0x61dfbb8a, 0x527d93e6), STCP(0x619a7dce, 0x52cf758f), + STCP(0x6154fb91, 0x53211d18), STCP(0x610f3505, 0x53728a4a), STCP(0x60c92a5a, 0x53c3bcea), + STCP(0x6082dbc1, 0x5414b4c1), STCP(0x603c496c, 0x54657194), STCP(0x5ff5738d, 0x54b5f32c), + STCP(0x5fae5a55, 0x55063951), STCP(0x5f66fdf5, 0x555643c8), STCP(0x5f1f5ea1, 0x55a6125c), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e8f57e2, 0x5644faf4), STCP(0x5e46f0dd, 0x5694148b), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5db55c86, 0x57319135), STCP(0x5d6c2f99, 0x577ff3da), + STCP(0x5d22c11c, 0x57ce1917), STCP(0x5cd91140, 0x581c00b3), STCP(0x5c8f203b, 0x5869aa79), + STCP(0x5c44ee40, 0x58b71632), STCP(0x5bfa7b82, 0x590443a7), STCP(0x5bafc837, 0x595132a2), + STCP(0x5b64d492, 0x599de2ee), STCP(0x5b19a0c8, 0x59ea5454), STCP(0x5ace2d0f, 0x5a36869f), + STCP(0x5a82799a, 0x5a82799a), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineTable360[] = { +# else +const PWord16 SineTable360[] = { +# endif + STCP(0x7fffffff, 0x00000000), STCP(0x7fffb025, 0x008efa17), STCP(0x7ffec095, 0x011df37c), + STCP(0x7ffd3153, 0x01aceb7c), STCP(0x7ffb025f, 0x023be165), STCP(0x7ff833bc, 0x02cad485), + STCP(0x7ff4c56e, 0x0359c428), STCP(0x7ff0b779, 0x03e8af9e), STCP(0x7fec09e2, 0x04779632), + STCP(0x7fe6bcaf, 0x05067734), STCP(0x7fe0cfe6, 0x059551f1), STCP(0x7fda4390, 0x062425b6), + STCP(0x7fd317b3, 0x06b2f1d2), STCP(0x7fcb4c5a, 0x0741b592), STCP(0x7fc2e18d, 0x07d07044), + STCP(0x7fb9d758, 0x085f2136), STCP(0x7fb02dc5, 0x08edc7b7), STCP(0x7fa5e4e0, 0x097c6313), + STCP(0x7f9afcb8, 0x0a0af299), STCP(0x7f8f7558, 0x0a997597), STCP(0x7f834ecf, 0x0b27eb5c), + STCP(0x7f76892e, 0x0bb65336), STCP(0x7f692482, 0x0c44ac72), STCP(0x7f5b20de, 0x0cd2f660), + STCP(0x7f4c7e53, 0x0d61304e), STCP(0x7f3d3cf3, 0x0def5989), STCP(0x7f2d5cd0, 0x0e7d7162), + STCP(0x7f1cde00, 0x0f0b7727), STCP(0x7f0bc096, 0x0f996a26), STCP(0x7efa04a7, 0x102749ae), + STCP(0x7ee7aa4b, 0x10b5150f), STCP(0x7ed4b197, 0x1142cb98), STCP(0x7ec11aa4, 0x11d06c96), + STCP(0x7eace589, 0x125df75b), STCP(0x7e981261, 0x12eb6b35), STCP(0x7e82a145, 0x1378c774), + STCP(0x7e6c9250, 0x14060b68), STCP(0x7e55e59d, 0x1493365f), STCP(0x7e3e9b49, 0x152047ab), + STCP(0x7e26b370, 0x15ad3e9a), STCP(0x7e0e2e31, 0x163a1a7e), STCP(0x7df50baa, 0x16c6daa6), + STCP(0x7ddb4bfb, 0x17537e63), STCP(0x7dc0ef43, 0x17e00505), STCP(0x7da5f5a4, 0x186c6ddd), + STCP(0x7d8a5f3f, 0x18f8b83c), STCP(0x7d6e2c36, 0x1984e373), STCP(0x7d515cae, 0x1a10eed2), + STCP(0x7d33f0c9, 0x1a9cd9ac), STCP(0x7d15e8ac, 0x1b28a351), STCP(0x7cf7447e, 0x1bb44b13), + STCP(0x7cd80464, 0x1c3fd045), STCP(0x7cb82884, 0x1ccb3237), STCP(0x7c97b108, 0x1d56703b), + STCP(0x7c769e17, 0x1de189a5), STCP(0x7c54efdb, 0x1e6c7dc7), STCP(0x7c32a67d, 0x1ef74bf3), + STCP(0x7c0fc229, 0x1f81f37b), STCP(0x7bec430a, 0x200c73b4), STCP(0x7bc8294c, 0x2096cbf0), + STCP(0x7ba3751c, 0x2120fb83), STCP(0x7b7e26a9, 0x21ab01c0), STCP(0x7b583e20, 0x2234ddfa), + STCP(0x7b31bbb1, 0x22be8f87), STCP(0x7b0a9f8d, 0x234815ba), STCP(0x7ae2e9e3, 0x23d16fe8), + STCP(0x7aba9ae5, 0x245a9d64), STCP(0x7a91b2c6, 0x24e39d85), STCP(0x7a6831b9, 0x256c6f9f), + STCP(0x7a3e17f1, 0x25f51307), STCP(0x7a1365a4, 0x267d8713), STCP(0x79e81b05, 0x2705cb19), + STCP(0x79bc384c, 0x278dde6e), STCP(0x798fbdaf, 0x2815c069), STCP(0x7962ab66, 0x289d7061), + STCP(0x793501a8, 0x2924edab), STCP(0x7906c0af, 0x29ac37a0), STCP(0x78d7e8b5, 0x2a334d95), + STCP(0x78a879f3, 0x2aba2ee3), STCP(0x787874a6, 0x2b40dae2), STCP(0x7847d908, 0x2bc750e9), + STCP(0x7816a758, 0x2c4d9050), STCP(0x77e4dfd1, 0x2cd39870), STCP(0x77b282b3, 0x2d5968a2), + STCP(0x777f903b, 0x2ddf003f), STCP(0x774c08aa, 0x2e645ea0), STCP(0x7717ec40, 0x2ee9831f), + STCP(0x76e33b3e, 0x2f6e6d15), STCP(0x76adf5e5, 0x2ff31bdd), STCP(0x76781c79, 0x30778ed2), + STCP(0x7641af3c, 0x30fbc54d), STCP(0x760aae72, 0x317fbeaa), STCP(0x75d31a60, 0x32037a45), + STCP(0x759af34b, 0x3286f778), STCP(0x75623979, 0x330a35a1), STCP(0x7528ed31, 0x338d341a), + STCP(0x74ef0ebb, 0x340ff242), STCP(0x74b49e5f, 0x34926f74), STCP(0x74799c65, 0x3514ab0d), + STCP(0x743e0917, 0x3596a46c), STCP(0x7401e4c0, 0x36185aee), STCP(0x73c52faa, 0x3699cdf1), + STCP(0x7387ea22, 0x371afcd4), STCP(0x734a1474, 0x379be6f6), STCP(0x730baeec, 0x381c8bb5), + STCP(0x72ccb9da, 0x389cea71), STCP(0x728d358b, 0x391d028b), STCP(0x724d224e, 0x399cd362), + STCP(0x720c8074, 0x3a1c5c56), STCP(0x71cb504d, 0x3a9b9cc9), STCP(0x7189922b, 0x3b1a941c), + STCP(0x7147465f, 0x3b9941b0), STCP(0x71046d3d, 0x3c17a4e8), STCP(0x70c10717, 0x3c95bd25), + STCP(0x707d1442, 0x3d1389cb), STCP(0x70389513, 0x3d910a3c), STCP(0x6ff389de, 0x3e0e3ddb), + STCP(0x6fadf2fb, 0x3e8b240e), STCP(0x6f67d0c0, 0x3f07bc37), STCP(0x6f212384, 0x3f8405bb), + STCP(0x6ed9eba1, 0x3fffffff), STCP(0x6e92296d, 0x407baa69), STCP(0x6e49dd44, 0x40f7045f), + STCP(0x6e01077f, 0x41720d45), STCP(0x6db7a879, 0x41ecc483), STCP(0x6d6dc08e, 0x42672980), + STCP(0x6d23501a, 0x42e13ba3), STCP(0x6cd85779, 0x435afa54), STCP(0x6c8cd70a, 0x43d464fa), + STCP(0x6c40cf2b, 0x444d7aff), STCP(0x6bf4403a, 0x44c63bca), STCP(0x6ba72a97, 0x453ea6c7), + STCP(0x6b598ea2, 0x45b6bb5d), STCP(0x6b0b6cbc, 0x462e78f8), STCP(0x6abcc546, 0x46a5df02), + STCP(0x6a6d98a3, 0x471cece6), STCP(0x6a1de736, 0x4793a210), STCP(0x69cdb161, 0x4809fdeb), + STCP(0x697cf789, 0x487fffe3), STCP(0x692bba13, 0x48f5a767), STCP(0x68d9f964, 0x496af3e1), + STCP(0x6887b5e1, 0x49dfe4c2), STCP(0x6834eff2, 0x4a547975), STCP(0x67e1a7ff, 0x4ac8b16b), + STCP(0x678dde6e, 0x4b3c8c11), STCP(0x673993a8, 0x4bb008d8), STCP(0x66e4c817, 0x4c23272f), + STCP(0x668f7c24, 0x4c95e687), STCP(0x6639b03a, 0x4d084651), STCP(0x65e364c3, 0x4d7a45fd), + STCP(0x658c9a2d, 0x4debe4fe), STCP(0x653550e1, 0x4e5d22c5), STCP(0x64dd894f, 0x4ecdfec6), + STCP(0x648543e3, 0x4f3e7874), STCP(0x642c810b, 0x4fae8f42), STCP(0x63d34136, 0x501e42a5), + STCP(0x637984d4, 0x508d9211), STCP(0x631f4c54, 0x50fc7cfa), STCP(0x62c49826, 0x516b02d8), + STCP(0x626968be, 0x51d92320), STCP(0x620dbe8a, 0x5246dd48), STCP(0x61b19a00, 0x52b430c8), + STCP(0x6154fb90, 0x53211d17), STCP(0x60f7e3b0, 0x538da1ae), STCP(0x609a52d2, 0x53f9be04), + STCP(0x603c496c, 0x54657194), STCP(0x5fddc7f3, 0x54d0bbd6), STCP(0x5f7ecedd, 0x553b9c45), + STCP(0x5f1f5ea0, 0x55a6125b), STCP(0x5ebf77b4, 0x56101d94), STCP(0x5e5f1a90, 0x5679bd6b), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5d9cff82, 0x574bb8e6), STCP(0x5d3b428b, 0x57b41383), + STCP(0x5cd91140, 0x581c00b3), STCP(0x5c766c1c, 0x58837ff3), STCP(0x5c13539a, 0x58ea90c3), + STCP(0x5bafc836, 0x595132a2), STCP(0x5b4bca6c, 0x59b7650f), STCP(0x5ae75ab8, 0x5a1d278c), + STCP(0x5a827999, 0x5a827999), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineTable320[] = { +# else +const PWord16 SineTable320[] = { +# endif + STCP(0x7fffffff, 0x00000000), STCP(0x7fff9aef, 0x00a0d951), STCP(0x7ffe6bbf, 0x0141b1a5), + STCP(0x7ffc726f, 0x01e287fc), STCP(0x7ff9af04, 0x02835b5a), STCP(0x7ff62182, 0x03242abf), + STCP(0x7ff1c9ef, 0x03c4f52f), STCP(0x7feca851, 0x0465b9aa), STCP(0x7fe6bcb0, 0x05067734), + STCP(0x7fe00716, 0x05a72ccf), STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd03e23, 0x06e87c3f), + STCP(0x7fc72ae2, 0x07891418), STCP(0x7fbd4dda, 0x0829a00c), STCP(0x7fb2a71b, 0x08ca1f1b), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f8df93c, 0x0aab450d), + STCP(0x7f802c52, 0x0b4b86a8), STCP(0x7f719611, 0x0bebb66c), STCP(0x7f62368f, 0x0c8bd35e), + STCP(0x7f520de6, 0x0d2bdc80), STCP(0x7f411c2f, 0x0dcbd0d5), STCP(0x7f2f6183, 0x0e6baf61), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7f0991c4, 0x0fab272b), STCP(0x7ef57cea, 0x104abe71), + STCP(0x7ee09f95, 0x10ea3bfd), STCP(0x7ecaf9e5, 0x11899ed3), STCP(0x7eb48bfb, 0x1228e5f8), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e85580c, 0x13671d3d), STCP(0x7e6c9251, 0x14060b68), + STCP(0x7e5304f2, 0x14a4d9f4), STCP(0x7e38b017, 0x154387e6), STCP(0x7e1d93ea, 0x15e21445), + STCP(0x7e01b096, 0x16807e15), STCP(0x7de50646, 0x171ec45c), STCP(0x7dc79529, 0x17bce621), + STCP(0x7da95d6c, 0x185ae269), STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d6a9ad5, 0x199666a0), + STCP(0x7d4a105d, 0x1a33ec9c), STCP(0x7d28c00c, 0x1ad14938), STCP(0x7d06aa16, 0x1b6e7b7a), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7cc02e15, 0x1ca85d12), STCP(0x7c9bc87a, 0x1d450a78), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7c50af2b, 0x1e7dd9a4), STCP(0x7c29fbee, 0x1f19f97b), + STCP(0x7c02849f, 0x1fb5e836), STCP(0x7bda497d, 0x2051a4dd), STCP(0x7bb14ac5, 0x20ed2e7b), + STCP(0x7b8788ba, 0x2188841a), STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b31bbb2, 0x22be8f87), + STCP(0x7b05b13d, 0x2359436c), STCP(0x7ad8e482, 0x23f3bf7e), STCP(0x7aab55ca, 0x248e02cb), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a4df380, 0x25c1db44), STCP(0x7a1e2082, 0x265b6e8a), + STCP(0x79ed8cad, 0x26f4c53e), STCP(0x79bc384d, 0x278dde6e), STCP(0x798a23b1, 0x2826b928), + STCP(0x79574f28, 0x28bf547b), STCP(0x7923bb01, 0x2957af74), STCP(0x78ef678f, 0x29efc925), + STCP(0x78ba5524, 0x2a87a09d), STCP(0x78848414, 0x2b1f34eb), STCP(0x784df4b3, 0x2bb68522), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77de9c5b, 0x2ce45589), STCP(0x77a5d413, 0x2d7ad3de), + STCP(0x776c4edb, 0x2e110a62), STCP(0x77320d0d, 0x2ea6f827), STCP(0x76f70f05, 0x2f3c9c40), + STCP(0x76bb5521, 0x2fd1f5c1), STCP(0x767edfbe, 0x306703bf), STCP(0x7641af3d, 0x30fbc54d), + STCP(0x7603c3fd, 0x31903982), STCP(0x75c51e61, 0x32245f72), STCP(0x7585becb, 0x32b83634), + STCP(0x7545a5a0, 0x334bbcde), STCP(0x7504d345, 0x33def287), STCP(0x74c34820, 0x3471d647), + STCP(0x74810499, 0x35046736), STCP(0x743e0918, 0x3596a46c), STCP(0x73fa5607, 0x36288d03), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x7370cae2, 0x374b5cb9), STCP(0x732af3a7, 0x37dc420c), + STCP(0x72e4668f, 0x386ccf2a), STCP(0x729d2409, 0x38fd032d), STCP(0x72552c85, 0x398cdd32), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x71c3204c, 0x3aab7fb7), STCP(0x71790c7e, 0x3b3a4672), + STCP(0x712e457f, 0x3bc8afa5), STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70969fca, 0x3ce465f3), + STCP(0x7049c203, 0x3d71b14d), STCP(0x6ffc32eb, 0x3dfe9ba1), STCP(0x6fadf2fc, 0x3e8b240e), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f0f6289, 0x3fa30bc1), STCP(0x6ebf12ff, 0x402e694c), + STCP(0x6e6e1492, 0x40b9617d), STCP(0x6e1c67c4, 0x4143f379), STCP(0x6dca0d14, 0x41ce1e65), + STCP(0x6d770506, 0x4257e166), STCP(0x6d23501b, 0x42e13ba4), STCP(0x6cceeed8, 0x436a2c45), + STCP(0x6c79e1c2, 0x43f2b271), STCP(0x6c242960, 0x447acd50), STCP(0x6bcdc639, 0x45027c0c), + STCP(0x6b76b8d6, 0x4589bdcf), STCP(0x6b1f01c0, 0x461091c2), STCP(0x6ac6a180, 0x4696f710), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a13e7b8, 0x47a27271), STCP(0x69b98f48, 0x482786dc), + STCP(0x695e8fe5, 0x48ac2957), STCP(0x6902ea1d, 0x4930590f), STCP(0x68a69e81, 0x49b41533), + STCP(0x6849ada3, 0x4a375cf5), STCP(0x67ec1817, 0x4aba2f84), STCP(0x678dde6e, 0x4b3c8c12), + STCP(0x672f013f, 0x4bbe71d1), STCP(0x66cf8120, 0x4c3fdff4), STCP(0x666f5ea6, 0x4cc0d5ae), + STCP(0x660e9a6a, 0x4d415234), STCP(0x65ad3505, 0x4dc154bb), STCP(0x654b2f10, 0x4e40dc79), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x648543e4, 0x4f3e7875), STCP(0x64215fe5, 0x4fbc8b22), + STCP(0x63bcddc7, 0x503a1fe5), STCP(0x6357be2a, 0x50b735f8), STCP(0x62f201ac, 0x5133cc94), + STCP(0x628ba8ef, 0x51afe2f6), STCP(0x6224b495, 0x522b7859), STCP(0x61bd253f, 0x52a68bfb), + STCP(0x6154fb91, 0x53211d18), STCP(0x60ec3830, 0x539b2af0), STCP(0x6082dbc1, 0x5414b4c1), + STCP(0x6018e6eb, 0x548db9cb), STCP(0x5fae5a55, 0x55063951), STCP(0x5f4336a7, 0x557e3292), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e6b2ca8, 0x566c8f55), STCP(0x5dfe47ad, 0x56e2f15d), + STCP(0x5d90ce45, 0x5758ca31), STCP(0x5d22c11c, 0x57ce1917), STCP(0x5cb420e0, 0x5842dd54), + STCP(0x5c44ee40, 0x58b71632), STCP(0x5bd529eb, 0x592ac2f7), STCP(0x5b64d492, 0x599de2ee), + STCP(0x5af3eee6, 0x5a107561), STCP(0x5a82799a, 0x5a82799a), +}; + + +# ifdef ENABLE_HR_MODE +#ifdef CR8_G_ADD_75MS + const PWord32 SineTable720[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7fffec08, 0x00477d17), STCP(0x7fffb025, 0x008efa17), + STCP(0x7fff4c53, 0x00d676eb), STCP(0x7ffec095, 0x011df37c), STCP(0x7ffe0cea, 0x01656fb4), + STCP(0x7ffd3153, 0x01aceb7c), STCP(0x7ffc2dcf, 0x01f466bf), STCP(0x7ffb025f, 0x023be165), + STCP(0x7ff9af03, 0x02835b59), STCP(0x7ff833bc, 0x02cad485), STCP(0x7ff6908a, 0x03124cd1), + STCP(0x7ff4c56e, 0x0359c428), STCP(0x7ff2d268, 0x03a13a74), STCP(0x7ff0b779, 0x03e8af9e), + STCP(0x7fee74a1, 0x0430238f), STCP(0x7fec09e2, 0x04779632), STCP(0x7fe9773c, 0x04bf0771), + STCP(0x7fe6bcaf, 0x05067734), STCP(0x7fe3da3d, 0x054de566), STCP(0x7fe0cfe6, 0x059551f1), + STCP(0x7fdd9dac, 0x05dcbcbe), STCP(0x7fda4390, 0x062425b6), STCP(0x7fd6c192, 0x066b8cc5), + STCP(0x7fd317b3, 0x06b2f1d2), STCP(0x7fcf45f6, 0x06fa54c9), STCP(0x7fcb4c5a, 0x0741b592), + STCP(0x7fc72ae1, 0x07891418), STCP(0x7fc2e18d, 0x07d07044), STCP(0x7fbe705f, 0x0817ca01), + STCP(0x7fb9d758, 0x085f2136), STCP(0x7fb51679, 0x08a675d0), STCP(0x7fb02dc5, 0x08edc7b7), + STCP(0x7fab1d3c, 0x093516d4), STCP(0x7fa5e4e0, 0x097c6313), STCP(0x7fa084b4, 0x09c3ac5c), + STCP(0x7f9afcb8, 0x0a0af299), STCP(0x7f954cee, 0x0a5235b4), STCP(0x7f8f7558, 0x0a997597), + STCP(0x7f8975f8, 0x0ae0b22c), STCP(0x7f834ecf, 0x0b27eb5c), STCP(0x7f7cffe1, 0x0b6f2112), + STCP(0x7f76892e, 0x0bb65336), STCP(0x7f6feab8, 0x0bfd81b3), STCP(0x7f692482, 0x0c44ac72), + STCP(0x7f62368e, 0x0c8bd35e), STCP(0x7f5b20de, 0x0cd2f660), STCP(0x7f53e374, 0x0d1a1562), + STCP(0x7f4c7e53, 0x0d61304e), STCP(0x7f44f17c, 0x0da8470d), STCP(0x7f3d3cf3, 0x0def5989), + STCP(0x7f3560b8, 0x0e3667ad), STCP(0x7f2d5cd0, 0x0e7d7162), STCP(0x7f25313c, 0x0ec47692), + STCP(0x7f1cde00, 0x0f0b7727), STCP(0x7f14631c, 0x0f52730a), STCP(0x7f0bc096, 0x0f996a26), + STCP(0x7f02f66e, 0x0fe05c64), STCP(0x7efa04a7, 0x102749ae), STCP(0x7ef0eb45, 0x106e31ef), + STCP(0x7ee7aa4b, 0x10b5150f), STCP(0x7ede41ba, 0x10fbf2fa), STCP(0x7ed4b197, 0x1142cb98), + STCP(0x7ecaf9e4, 0x11899ed3), STCP(0x7ec11aa4, 0x11d06c96), STCP(0x7eb713da, 0x121734cb), + STCP(0x7eace589, 0x125df75b), STCP(0x7ea28fb5, 0x12a4b431), STCP(0x7e981261, 0x12eb6b35), + STCP(0x7e8d6d90, 0x13321c53), STCP(0x7e82a145, 0x1378c774), STCP(0x7e77ad84, 0x13bf6c82), + STCP(0x7e6c9250, 0x14060b68), STCP(0x7e614fac, 0x144ca40e), STCP(0x7e55e59d, 0x1493365f), + STCP(0x7e4a5425, 0x14d9c245), STCP(0x7e3e9b49, 0x152047ab), STCP(0x7e32bb0b, 0x1566c679), + STCP(0x7e26b370, 0x15ad3e9a), STCP(0x7e1a847b, 0x15f3aff8), STCP(0x7e0e2e31, 0x163a1a7e), + STCP(0x7e01b095, 0x16807e14), STCP(0x7df50baa, 0x16c6daa6), STCP(0x7de83f76, 0x170d301d), + STCP(0x7ddb4bfb, 0x17537e63), STCP(0x7dce313e, 0x1799c562), STCP(0x7dc0ef43, 0x17e00505), + STCP(0x7db3860e, 0x18263d35), STCP(0x7da5f5a4, 0x186c6ddd), STCP(0x7d983e08, 0x18b296e7), + STCP(0x7d8a5f3f, 0x18f8b83c), STCP(0x7d7c594d, 0x193ed1c8), STCP(0x7d6e2c36, 0x1984e373), + STCP(0x7d5fd800, 0x19caed28), STCP(0x7d515cae, 0x1a10eed2), STCP(0x7d42ba45, 0x1a56e85b), + STCP(0x7d33f0c9, 0x1a9cd9ac), STCP(0x7d25003f, 0x1ae2c2b0), STCP(0x7d15e8ac, 0x1b28a351), + STCP(0x7d06aa15, 0x1b6e7b7a), STCP(0x7cf7447e, 0x1bb44b13), STCP(0x7ce7b7ec, 0x1bfa1209), + STCP(0x7cd80464, 0x1c3fd045), STCP(0x7cc829ea, 0x1c8585b0), STCP(0x7cb82884, 0x1ccb3237), + STCP(0x7ca80037, 0x1d10d5c1), STCP(0x7c97b108, 0x1d56703b), STCP(0x7c873afb, 0x1d9c018f), + STCP(0x7c769e17, 0x1de189a5), STCP(0x7c65da60, 0x1e27086a), STCP(0x7c54efdb, 0x1e6c7dc7), + STCP(0x7c43de8d, 0x1eb1e9a6), STCP(0x7c32a67d, 0x1ef74bf3), STCP(0x7c2147af, 0x1f3ca496), + STCP(0x7c0fc229, 0x1f81f37b), STCP(0x7bfe15f0, 0x1fc7388d), STCP(0x7bec430a, 0x200c73b4), + STCP(0x7bda497c, 0x2051a4dd), STCP(0x7bc8294c, 0x2096cbf0), STCP(0x7bb5e27f, 0x20dbe8da), + STCP(0x7ba3751c, 0x2120fb83), STCP(0x7b90e128, 0x216603d7), STCP(0x7b7e26a9, 0x21ab01c0), + STCP(0x7b6b45a4, 0x21eff528), STCP(0x7b583e20, 0x2234ddfa), STCP(0x7b451022, 0x2279bc21), + STCP(0x7b31bbb1, 0x22be8f87), STCP(0x7b1e40d3, 0x23035817), STCP(0x7b0a9f8d, 0x234815ba), + STCP(0x7af6d7e5, 0x238cc85c), STCP(0x7ae2e9e3, 0x23d16fe8), STCP(0x7aced58b, 0x24160c47), + STCP(0x7aba9ae5, 0x245a9d64), STCP(0x7aa639f7, 0x249f232b), STCP(0x7a91b2c6, 0x24e39d85), + STCP(0x7a7d055a, 0x25280c5d), STCP(0x7a6831b9, 0x256c6f9f), STCP(0x7a5337e9, 0x25b0c734), + STCP(0x7a3e17f1, 0x25f51307), STCP(0x7a28d1d8, 0x26395303), STCP(0x7a1365a4, 0x267d8713), + STCP(0x79fdd35b, 0x26c1af21), STCP(0x79e81b05, 0x2705cb19), STCP(0x79d23ca9, 0x2749dae4), + STCP(0x79bc384c, 0x278dde6e), STCP(0x79a60df7, 0x27d1d5a2), STCP(0x798fbdaf, 0x2815c069), + STCP(0x7979477c, 0x28599eb0), STCP(0x7962ab66, 0x289d7061), STCP(0x794be972, 0x28e13566), + STCP(0x793501a8, 0x2924edab), STCP(0x791df40f, 0x2968991b), STCP(0x7906c0af, 0x29ac37a0), + STCP(0x78ef678e, 0x29efc925), STCP(0x78d7e8b5, 0x2a334d95), STCP(0x78c04429, 0x2a76c4dc), + STCP(0x78a879f3, 0x2aba2ee3), STCP(0x78908a1a, 0x2afd8b97), STCP(0x787874a6, 0x2b40dae2), + STCP(0x7860399d, 0x2b841caf), STCP(0x7847d908, 0x2bc750e9), STCP(0x782f52ef, 0x2c0a777b), + STCP(0x7816a758, 0x2c4d9050), STCP(0x77fdd64b, 0x2c909b54), STCP(0x77e4dfd1, 0x2cd39870), + STCP(0x77cbc3f1, 0x2d168792), STCP(0x77b282b3, 0x2d5968a2), STCP(0x77991c1e, 0x2d9c3b8e), + STCP(0x777f903b, 0x2ddf003f), STCP(0x7765df12, 0x2e21b6a2), STCP(0x774c08aa, 0x2e645ea0), + STCP(0x77320d0c, 0x2ea6f826), STCP(0x7717ec40, 0x2ee9831f), STCP(0x76fda64e, 0x2f2bff76), + STCP(0x76e33b3e, 0x2f6e6d15), STCP(0x76c8ab18, 0x2fb0cbea), STCP(0x76adf5e5, 0x2ff31bdd), + STCP(0x76931bae, 0x30355cdc), STCP(0x76781c79, 0x30778ed2), STCP(0x765cf850, 0x30b9b1a9), + STCP(0x7641af3c, 0x30fbc54d), STCP(0x76264144, 0x313dc9aa), STCP(0x760aae72, 0x317fbeaa), + STCP(0x75eef6ce, 0x31c1a43a), STCP(0x75d31a60, 0x32037a45), STCP(0x75b71931, 0x324540b6), + STCP(0x759af34b, 0x3286f778), STCP(0x757ea8b5, 0x32c89e78), STCP(0x75623979, 0x330a35a1), + STCP(0x7545a59f, 0x334bbcde), STCP(0x7528ed31, 0x338d341a), STCP(0x750c1038, 0x33ce9b42), + STCP(0x74ef0ebb, 0x340ff242), STCP(0x74d1e8c5, 0x34513903), STCP(0x74b49e5f, 0x34926f74), + STCP(0x74972f91, 0x34d3957e), STCP(0x74799c65, 0x3514ab0d), STCP(0x745be4e4, 0x3555b00e), + STCP(0x743e0917, 0x3596a46c), STCP(0x74200908, 0x35d78813), STCP(0x7401e4c0, 0x36185aee), + STCP(0x73e39c48, 0x36591cea), STCP(0x73c52faa, 0x3699cdf1), STCP(0x73a69ef0, 0x36da6df1), + STCP(0x7387ea22, 0x371afcd4), STCP(0x7369114b, 0x375b7a87), STCP(0x734a1474, 0x379be6f6), + STCP(0x732af3a6, 0x37dc420c), STCP(0x730baeec, 0x381c8bb5), STCP(0x72ec4650, 0x385cc3de), + STCP(0x72ccb9da, 0x389cea71), STCP(0x72ad0995, 0x38dcff5d), STCP(0x728d358b, 0x391d028b), + STCP(0x726d3dc5, 0x395cf3e9), STCP(0x724d224e, 0x399cd362), STCP(0x722ce330, 0x39dca0e2), + STCP(0x720c8074, 0x3a1c5c56), STCP(0x71ebfa25, 0x3a5c05aa), STCP(0x71cb504d, 0x3a9b9cc9), + STCP(0x71aa82f6, 0x3adb21a0), STCP(0x7189922b, 0x3b1a941c), STCP(0x71687df5, 0x3b59f428), + STCP(0x7147465f, 0x3b9941b0), STCP(0x7125eb74, 0x3bd87ca1), STCP(0x71046d3d, 0x3c17a4e8), + STCP(0x70e2cbc5, 0x3c56ba70), STCP(0x70c10717, 0x3c95bd25), STCP(0x709f1f3d, 0x3cd4acf5), + STCP(0x707d1442, 0x3d1389cb), STCP(0x705ae630, 0x3d525394), STCP(0x70389513, 0x3d910a3c), + STCP(0x701620f4, 0x3dcfadaf), STCP(0x6ff389de, 0x3e0e3ddb), STCP(0x6fd0cfdd, 0x3e4cbaac), + STCP(0x6fadf2fb, 0x3e8b240e), STCP(0x6f8af343, 0x3ec979ed), STCP(0x6f67d0c0, 0x3f07bc37), + STCP(0x6f448b7d, 0x3f45ead7), STCP(0x6f212384, 0x3f8405bb), STCP(0x6efd98e2, 0x3fc20ccf), + STCP(0x6ed9eba1, 0x3fffffff), STCP(0x6eb61bcb, 0x403ddf39), STCP(0x6e92296d, 0x407baa69), + STCP(0x6e6e1492, 0x40b9617c), STCP(0x6e49dd44, 0x40f7045f), STCP(0x6e25838f, 0x413492fd), + STCP(0x6e01077f, 0x41720d45), STCP(0x6ddc691e, 0x41af7323), STCP(0x6db7a879, 0x41ecc483), + STCP(0x6d92c59a, 0x422a0154), STCP(0x6d6dc08e, 0x42672980), STCP(0x6d48995f, 0x42a43cf7), + STCP(0x6d23501a, 0x42e13ba3), STCP(0x6cfde4c9, 0x431e2573), STCP(0x6cd85779, 0x435afa54), + STCP(0x6cb2a836, 0x4397ba32), STCP(0x6c8cd70a, 0x43d464fa), STCP(0x6c66e403, 0x4410fa9a), + STCP(0x6c40cf2b, 0x444d7aff), STCP(0x6c1a988f, 0x4489e615), STCP(0x6bf4403a, 0x44c63bca), + STCP(0x6bcdc639, 0x45027c0c), STCP(0x6ba72a97, 0x453ea6c7), STCP(0x6b806d61, 0x457abbe8), + STCP(0x6b598ea2, 0x45b6bb5d), STCP(0x6b328e67, 0x45f2a513), STCP(0x6b0b6cbc, 0x462e78f8), + STCP(0x6ae429ad, 0x466a36f9), STCP(0x6abcc546, 0x46a5df02), STCP(0x6a953f94, 0x46e17102), + STCP(0x6a6d98a3, 0x471cece6), STCP(0x6a45d080, 0x4758529c), STCP(0x6a1de736, 0x4793a210), + STCP(0x69f5dcd2, 0x47cedb30), STCP(0x69cdb161, 0x4809fdeb), STCP(0x69a564ef, 0x48450a2d), + STCP(0x697cf789, 0x487fffe3), STCP(0x6954693b, 0x48badefd), STCP(0x692bba13, 0x48f5a767), + STCP(0x6902ea1c, 0x4930590e), STCP(0x68d9f964, 0x496af3e1), STCP(0x68b0e7f6, 0x49a577ce), + STCP(0x6887b5e1, 0x49dfe4c2), STCP(0x685e6331, 0x4a1a3aaa), STCP(0x6834eff2, 0x4a547975), + STCP(0x680b5c33, 0x4a8ea111), STCP(0x67e1a7ff, 0x4ac8b16b), STCP(0x67b7d363, 0x4b02aa71), + STCP(0x678dde6e, 0x4b3c8c11), STCP(0x6763c92b, 0x4b76563a), STCP(0x673993a8, 0x4bb008d8), + STCP(0x670f3df2, 0x4be9a3db), STCP(0x66e4c817, 0x4c23272f), STCP(0x66ba3223, 0x4c5c92c4), + STCP(0x668f7c24, 0x4c95e687), STCP(0x6664a627, 0x4ccf2267), STCP(0x6639b03a, 0x4d084651), + STCP(0x660e9a69, 0x4d415233), STCP(0x65e364c3, 0x4d7a45fd), STCP(0x65b80f55, 0x4db3219c), + STCP(0x658c9a2d, 0x4debe4fe), STCP(0x65610557, 0x4e249011), STCP(0x653550e1, 0x4e5d22c5), + STCP(0x65097cda, 0x4e959d07), STCP(0x64dd894f, 0x4ecdfec6), STCP(0x64b1764d, 0x4f0647f0), + STCP(0x648543e3, 0x4f3e7874), STCP(0x6458f21d, 0x4f769040), STCP(0x642c810b, 0x4fae8f42), + STCP(0x63fff0b9, 0x4fe6756a), STCP(0x63d34136, 0x501e42a5), STCP(0x63a6728f, 0x5055f6e2), + STCP(0x637984d4, 0x508d9211), STCP(0x634c7810, 0x50c5141e), STCP(0x631f4c54, 0x50fc7cfa), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62c49826, 0x516b02d8), STCP(0x62970fd2, 0x51a21fb7), + STCP(0x626968be, 0x51d92320), STCP(0x623ba2f6, 0x52100d01), STCP(0x620dbe8a, 0x5246dd48), + STCP(0x61dfbb89, 0x527d93e6), STCP(0x61b19a00, 0x52b430c8), STCP(0x618359fd, 0x52eab3de), + STCP(0x6154fb90, 0x53211d17), STCP(0x61267ec7, 0x53576c62), STCP(0x60f7e3b0, 0x538da1ae), + STCP(0x60c92a59, 0x53c3bce9), STCP(0x609a52d2, 0x53f9be04), STCP(0x606b5d28, 0x542fa4ed), + STCP(0x603c496c, 0x54657194), STCP(0x600d17aa, 0x549b23e7), STCP(0x5fddc7f3, 0x54d0bbd6), + STCP(0x5fae5a54, 0x55063950), STCP(0x5f7ecedd, 0x553b9c45), STCP(0x5f4f259c, 0x5570e4a3), + STCP(0x5f1f5ea0, 0x55a6125b), STCP(0x5eef79f8, 0x55db255b), STCP(0x5ebf77b4, 0x56101d94), + STCP(0x5e8f57e2, 0x5644faf4), STCP(0x5e5f1a90, 0x5679bd6b), STCP(0x5e2ebfcf, 0x56ae64e9), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5dcdb239, 0x571762b6), STCP(0x5d9cff82, 0x574bb8e6), + STCP(0x5d6c2f99, 0x577ff3da), STCP(0x5d3b428b, 0x57b41383), STCP(0x5d0a3868, 0x57e817d1), + STCP(0x5cd91140, 0x581c00b3), STCP(0x5ca7cd21, 0x584fce19), STCP(0x5c766c1c, 0x58837ff3), + STCP(0x5c44ee3f, 0x58b71631), STCP(0x5c13539a, 0x58ea90c3), STCP(0x5be19c3c, 0x591def98), + STCP(0x5bafc836, 0x595132a2), STCP(0x5b7dd796, 0x598459ce), STCP(0x5b4bca6c, 0x59b7650f), + STCP(0x5b19a0c7, 0x59ea5454), STCP(0x5ae75ab8, 0x5a1d278c), STCP(0x5ab4f84f, 0x5a4fdea9), + STCP(0x5a827999, 0x5a827999) +}; +#endif +const PWord32 SineTable960[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7ffff4c4, 0x00359dd2), STCP(0x7fffd314, 0x006b3b9b), + STCP(0x7fff9aee, 0x00a0d951), STCP(0x7fff4c53, 0x00d676eb), STCP(0x7ffee743, 0x010c1460), + STCP(0x7ffe6bbe, 0x0141b1a5), STCP(0x7ffdd9c3, 0x01774eb2), STCP(0x7ffd3153, 0x01aceb7c), + STCP(0x7ffc726e, 0x01e287fc), STCP(0x7ffb9d14, 0x02182427), STCP(0x7ffab146, 0x024dbff4), + STCP(0x7ff9af03, 0x02835b59), STCP(0x7ff8964c, 0x02b8f64e), STCP(0x7ff76720, 0x02ee90c8), + STCP(0x7ff62181, 0x03242abf), STCP(0x7ff4c56e, 0x0359c428), STCP(0x7ff352e7, 0x038f5cfb), + STCP(0x7ff1c9ee, 0x03c4f52e), STCP(0x7ff02a81, 0x03fa8cb8), STCP(0x7fee74a1, 0x0430238f), + STCP(0x7feca850, 0x0465b9aa), STCP(0x7feac58c, 0x049b4f00), STCP(0x7fe8cc56, 0x04d0e386), + STCP(0x7fe6bcaf, 0x05067734), STCP(0x7fe49697, 0x053c0a01), STCP(0x7fe25a0e, 0x05719be2), + STCP(0x7fe00715, 0x05a72ccf), STCP(0x7fdd9dac, 0x05dcbcbe), STCP(0x7fdb1dd4, 0x06124ba5), + STCP(0x7fd8878d, 0x0647d97c), STCP(0x7fd5dad7, 0x067d6639), STCP(0x7fd317b3, 0x06b2f1d2), + STCP(0x7fd03e22, 0x06e87c3f), STCP(0x7fcd4e23, 0x071e0575), STCP(0x7fca47b8, 0x07538d6b), + STCP(0x7fc72ae1, 0x07891418), STCP(0x7fc3f79f, 0x07be9973), STCP(0x7fc0adf1, 0x07f41d72), + STCP(0x7fbd4dd9, 0x0829a00b), STCP(0x7fb9d758, 0x085f2136), STCP(0x7fb64a6d, 0x0894a0e9), + STCP(0x7fb2a71a, 0x08ca1f1b), STCP(0x7faeed5e, 0x08ff9bc2), STCP(0x7fab1d3c, 0x093516d4), + STCP(0x7fa736b3, 0x096a9049), STCP(0x7fa339c4, 0x09a00817), STCP(0x7f9f2670, 0x09d57e35), + STCP(0x7f9afcb8, 0x0a0af299), STCP(0x7f96bc9b, 0x0a40653a), STCP(0x7f92661c, 0x0a75d60e), + STCP(0x7f8df93b, 0x0aab450d), STCP(0x7f8975f8, 0x0ae0b22c), STCP(0x7f84dc54, 0x0b161d63), + STCP(0x7f802c51, 0x0b4b86a8), STCP(0x7f7b65ee, 0x0b80edf1), STCP(0x7f76892e, 0x0bb65336), + STCP(0x7f719610, 0x0bebb66c), STCP(0x7f6c8c95, 0x0c21178c), STCP(0x7f676cbf, 0x0c56768a), + STCP(0x7f62368e, 0x0c8bd35e), STCP(0x7f5cea04, 0x0cc12dff), STCP(0x7f578720, 0x0cf68662), + STCP(0x7f520de5, 0x0d2bdc80), STCP(0x7f4c7e53, 0x0d61304e), STCP(0x7f46d86b, 0x0d9681c2), + STCP(0x7f411c2e, 0x0dcbd0d5), STCP(0x7f3b499c, 0x0e011d7c), STCP(0x7f3560b8, 0x0e3667ad), + STCP(0x7f2f6182, 0x0e6baf61), STCP(0x7f294bfc, 0x0ea0f48c), STCP(0x7f232025, 0x0ed63727), + STCP(0x7f1cde00, 0x0f0b7727), STCP(0x7f16858d, 0x0f40b483), STCP(0x7f1016cd, 0x0f75ef32), + STCP(0x7f0991c3, 0x0fab272b), STCP(0x7f02f66e, 0x0fe05c64), STCP(0x7efc44cf, 0x10158ed4), + STCP(0x7ef57cea, 0x104abe71), STCP(0x7eee9ebd, 0x107feb33), STCP(0x7ee7aa4b, 0x10b5150f), + STCP(0x7ee09f94, 0x10ea3bfd), STCP(0x7ed97e9b, 0x111f5ff3), STCP(0x7ed24760, 0x115480e9), + STCP(0x7ecaf9e4, 0x11899ed3), STCP(0x7ec39629, 0x11beb9aa), STCP(0x7ebc1c30, 0x11f3d164), + STCP(0x7eb48bfa, 0x1228e5f7), STCP(0x7eace589, 0x125df75b), STCP(0x7ea528df, 0x12930586), + STCP(0x7e9d55fb, 0x12c8106e), STCP(0x7e956ce0, 0x12fd180b), STCP(0x7e8d6d90, 0x13321c53), + STCP(0x7e85580b, 0x13671d3d), STCP(0x7e7d2c53, 0x139c1abf), STCP(0x7e74ea69, 0x13d114d0), + STCP(0x7e6c9250, 0x14060b68), STCP(0x7e642407, 0x143afe7b), STCP(0x7e5b9f92, 0x146fee02), + STCP(0x7e5304f1, 0x14a4d9f3), STCP(0x7e4a5425, 0x14d9c245), STCP(0x7e418d31, 0x150ea6ef), + STCP(0x7e38b016, 0x154387e6), STCP(0x7e2fbcd5, 0x15786522), STCP(0x7e26b370, 0x15ad3e9a), + STCP(0x7e1d93e9, 0x15e21444), STCP(0x7e145e41, 0x1616e618), STCP(0x7e0b1279, 0x164bb40b), + STCP(0x7e01b095, 0x16807e14), STCP(0x7df83894, 0x16b5442b), STCP(0x7deeaa79, 0x16ea0646), + STCP(0x7de50645, 0x171ec45c), STCP(0x7ddb4bfb, 0x17537e63), STCP(0x7dd17b9b, 0x17883452), + STCP(0x7dc79528, 0x17bce621), STCP(0x7dbd98a3, 0x17f193c5), STCP(0x7db3860e, 0x18263d35), + STCP(0x7da95d6b, 0x185ae269), STCP(0x7d9f1ebc, 0x188f8357), STCP(0x7d94ca02, 0x18c41ff6), + STCP(0x7d8a5f3f, 0x18f8b83c), STCP(0x7d7fde75, 0x192d4c21), STCP(0x7d7547a6, 0x1961db9b), + STCP(0x7d6a9ad4, 0x199666a0), STCP(0x7d5fd800, 0x19caed28), STCP(0x7d54ff2d, 0x19ff6f2a), + STCP(0x7d4a105c, 0x1a33ec9c), STCP(0x7d3f0b8f, 0x1a686575), STCP(0x7d33f0c9, 0x1a9cd9ac), + STCP(0x7d28c00b, 0x1ad14938), STCP(0x7d1d7957, 0x1b05b40e), STCP(0x7d121caf, 0x1b3a1a27), + STCP(0x7d06aa15, 0x1b6e7b7a), STCP(0x7cfb218b, 0x1ba2d7fc), STCP(0x7cef8314, 0x1bd72fa4), + STCP(0x7ce3ceb1, 0x1c0b826a), STCP(0x7cd80464, 0x1c3fd045), STCP(0x7ccc242f, 0x1c74192a), + STCP(0x7cc02e14, 0x1ca85d12), STCP(0x7cb42216, 0x1cdc9bf2), STCP(0x7ca80037, 0x1d10d5c1), + STCP(0x7c9bc879, 0x1d450a78), STCP(0x7c8f7add, 0x1d793a0b), STCP(0x7c831766, 0x1dad6473), + STCP(0x7c769e17, 0x1de189a5), STCP(0x7c6a0ef1, 0x1e15a99a), STCP(0x7c5d69f6, 0x1e49c447), + STCP(0x7c50af2a, 0x1e7dd9a3), STCP(0x7c43de8d, 0x1eb1e9a6), STCP(0x7c36f823, 0x1ee5f447), + STCP(0x7c29fbed, 0x1f19f97b), STCP(0x7c1ce9ee, 0x1f4df93a), STCP(0x7c0fc229, 0x1f81f37b), + STCP(0x7c02849f, 0x1fb5e835), STCP(0x7bf53152, 0x1fe9d75f), STCP(0x7be7c846, 0x201dc0ef), + STCP(0x7bda497c, 0x2051a4dd), STCP(0x7bccb4f7, 0x2085831e), STCP(0x7bbf0ab9, 0x20b95bac), + STCP(0x7bb14ac4, 0x20ed2e7b), STCP(0x7ba3751c, 0x2120fb83), STCP(0x7b9589c2, 0x2154c2bb), + STCP(0x7b8788b9, 0x2188841a), STCP(0x7b797204, 0x21bc3f97), STCP(0x7b6b45a4, 0x21eff528), + STCP(0x7b5d039d, 0x2223a4c5), STCP(0x7b4eabf0, 0x22574e65), STCP(0x7b403ea1, 0x228af1fe), + STCP(0x7b31bbb1, 0x22be8f87), STCP(0x7b232324, 0x22f226f8), STCP(0x7b1474fc, 0x2325b847), + STCP(0x7b05b13c, 0x2359436c), STCP(0x7af6d7e5, 0x238cc85c), STCP(0x7ae7e8fb, 0x23c04710), + STCP(0x7ad8e481, 0x23f3bf7e), STCP(0x7ac9ca79, 0x2427319d), STCP(0x7aba9ae5, 0x245a9d64), + STCP(0x7aab55c9, 0x248e02ca), STCP(0x7a9bfb26, 0x24c161c7), STCP(0x7a8c8b00, 0x24f4ba50), + STCP(0x7a7d055a, 0x25280c5d), STCP(0x7a6d6a36, 0x255b57e6), STCP(0x7a5db997, 0x258e9ce0), + STCP(0x7a4df37f, 0x25c1db43), STCP(0x7a3e17f1, 0x25f51307), STCP(0x7a2e26f1, 0x26284421), + STCP(0x7a1e2081, 0x265b6e8a), STCP(0x7a0e04a3, 0x268e9238), STCP(0x79fdd35b, 0x26c1af21), + STCP(0x79ed8cac, 0x26f4c53e), STCP(0x79dd3097, 0x2727d485), STCP(0x79ccbf21, 0x275adcee), + STCP(0x79bc384c, 0x278dde6e), STCP(0x79ab9c1b, 0x27c0d8fe), STCP(0x799aea91, 0x27f3cc94), + STCP(0x798a23b0, 0x2826b928), STCP(0x7979477c, 0x28599eb0), STCP(0x796855f8, 0x288c7d24), + STCP(0x79574f27, 0x28bf547a), STCP(0x7946330b, 0x28f224aa), STCP(0x793501a8, 0x2924edab), + STCP(0x7923bb00, 0x2957af74), STCP(0x79125f18, 0x298a69fc), STCP(0x7900edf1, 0x29bd1d3a), + STCP(0x78ef678e, 0x29efc925), STCP(0x78ddcbf4, 0x2a226db4), STCP(0x78cc1b25, 0x2a550adf), + STCP(0x78ba5523, 0x2a87a09c), STCP(0x78a879f3, 0x2aba2ee3), STCP(0x78968997, 0x2aecb5ab), + STCP(0x78848413, 0x2b1f34eb), STCP(0x78726969, 0x2b51ac9a), STCP(0x7860399d, 0x2b841caf), + STCP(0x784df4b2, 0x2bb68521), STCP(0x783b9aac, 0x2be8e5e8), STCP(0x78292b8c, 0x2c1b3efb), + STCP(0x7816a758, 0x2c4d9050), STCP(0x78040e11, 0x2c7fd9df), STCP(0x77f15fbb, 0x2cb21ba0), + STCP(0x77de9c5a, 0x2ce45589), STCP(0x77cbc3f1, 0x2d168792), STCP(0x77b8d683, 0x2d48b1b1), + STCP(0x77a5d413, 0x2d7ad3de), STCP(0x7792bca4, 0x2dacee10), STCP(0x777f903b, 0x2ddf003f), + STCP(0x776c4eda, 0x2e110a62), STCP(0x7758f885, 0x2e430c6f), STCP(0x77458d3f, 0x2e75065e), + STCP(0x77320d0c, 0x2ea6f826), STCP(0x771e77ef, 0x2ed8e1bf), STCP(0x770acdeb, 0x2f0ac320), + STCP(0x76f70f04, 0x2f3c9c3f), STCP(0x76e33b3e, 0x2f6e6d15), STCP(0x76cf529b, 0x2fa03599), + STCP(0x76bb5520, 0x2fd1f5c1), STCP(0x76a742d0, 0x3003ad85), STCP(0x76931bae, 0x30355cdc), + STCP(0x767edfbd, 0x306703be), STCP(0x766a8f03, 0x3098a222), STCP(0x76562981, 0x30ca37ff), + STCP(0x7641af3c, 0x30fbc54d), STCP(0x762d2037, 0x312d4a02), STCP(0x76187c76, 0x315ec617), + STCP(0x7603c3fc, 0x31903982), STCP(0x75eef6ce, 0x31c1a43a), STCP(0x75da14ee, 0x31f30638), + STCP(0x75c51e60, 0x32245f72), STCP(0x75b01329, 0x3255afe0), STCP(0x759af34b, 0x3286f778), + STCP(0x7585beca, 0x32b83634), STCP(0x757075ab, 0x32e96c09), STCP(0x755b17f1, 0x331a98ef), + STCP(0x7545a59f, 0x334bbcde), STCP(0x75301eba, 0x337cd7cc), STCP(0x751a8345, 0x33ade9b2), + STCP(0x7504d344, 0x33def287), STCP(0x74ef0ebb, 0x340ff242), STCP(0x74d935ad, 0x3440e8da), + STCP(0x74c3481f, 0x3471d647), STCP(0x74ad4614, 0x34a2ba80), STCP(0x74972f91, 0x34d3957e), + STCP(0x74810498, 0x35046736), STCP(0x746ac52e, 0x35352fa1), STCP(0x74547157, 0x3565eeb6), + STCP(0x743e0917, 0x3596a46c), STCP(0x74278c71, 0x35c750bb), STCP(0x7410fb6a, 0x35f7f39b), + STCP(0x73fa5606, 0x36288d03), STCP(0x73e39c48, 0x36591cea), STCP(0x73ccce35, 0x3689a347), + STCP(0x73b5ebd0, 0x36ba2013), STCP(0x739ef51e, 0x36ea9345), STCP(0x7387ea22, 0x371afcd4), + STCP(0x7370cae1, 0x374b5cb8), STCP(0x7359975f, 0x377bb2e8), STCP(0x73424f9f, 0x37abff5c), + STCP(0x732af3a6, 0x37dc420c), STCP(0x73138379, 0x380c7aee), STCP(0x72fbff1a, 0x383ca9fb), + STCP(0x72e4668e, 0x386ccf29), STCP(0x72ccb9da, 0x389cea71), STCP(0x72b4f901, 0x38ccfbcb), + STCP(0x729d2408, 0x38fd032d), STCP(0x72853af2, 0x392d008f), STCP(0x726d3dc5, 0x395cf3e9), + STCP(0x72552c84, 0x398cdd32), STCP(0x723d0733, 0x39bcbc62), STCP(0x7224cdd7, 0x39ec9171), + STCP(0x720c8074, 0x3a1c5c56), STCP(0x71f41f0e, 0x3a4c1d09), STCP(0x71dba9aa, 0x3a7bd381), + STCP(0x71c3204b, 0x3aab7fb6), STCP(0x71aa82f6, 0x3adb21a0), STCP(0x7191d1b0, 0x3b0ab937), + STCP(0x71790c7d, 0x3b3a4671), STCP(0x71603360, 0x3b69c947), STCP(0x7147465f, 0x3b9941b0), + STCP(0x712e457e, 0x3bc8afa4), STCP(0x711530c1, 0x3bf8131b), STCP(0x70fc082d, 0x3c276c0c), + STCP(0x70e2cbc5, 0x3c56ba70), STCP(0x70c97b8f, 0x3c85fe3c), STCP(0x70b0178f, 0x3cb5376b), + STCP(0x70969fc9, 0x3ce465f2), STCP(0x707d1442, 0x3d1389cb), STCP(0x706374fe, 0x3d42a2ec), + STCP(0x7049c202, 0x3d71b14d), STCP(0x702ffb53, 0x3da0b4e6), STCP(0x701620f4, 0x3dcfadaf), + STCP(0x6ffc32ea, 0x3dfe9ba0), STCP(0x6fe2313b, 0x3e2d7eb0), STCP(0x6fc81be9, 0x3e5c56d8), + STCP(0x6fadf2fb, 0x3e8b240e), STCP(0x6f93b675, 0x3eb9e64b), STCP(0x6f79665a, 0x3ee89d86), + STCP(0x6f5f02b1, 0x3f1749b7), STCP(0x6f448b7d, 0x3f45ead7), STCP(0x6f2a00c3, 0x3f7480dd), + STCP(0x6f0f6288, 0x3fa30bc0), STCP(0x6ef4b0d0, 0x3fd18b79), STCP(0x6ed9eba1, 0x3fffffff), + STCP(0x6ebf12fe, 0x402e694b), STCP(0x6ea426ed, 0x405cc754), STCP(0x6e892772, 0x408b1a12), + STCP(0x6e6e1492, 0x40b9617c), STCP(0x6e52ee51, 0x40e79d8c), STCP(0x6e37b4b6, 0x4115ce38), + STCP(0x6e1c67c3, 0x4143f378), STCP(0x6e01077f, 0x41720d45), STCP(0x6de593ed, 0x41a01b96), + STCP(0x6dca0d14, 0x41ce1e64), STCP(0x6dae72f6, 0x41fc15a6), STCP(0x6d92c59a, 0x422a0154), + STCP(0x6d770505, 0x4257e166), STCP(0x6d5b313a, 0x4285b5d4), STCP(0x6d3f4a3f, 0x42b37e95), + STCP(0x6d23501a, 0x42e13ba3), STCP(0x6d0742ce, 0x430eecf5), STCP(0x6ceb2260, 0x433c9283), + STCP(0x6cceeed7, 0x436a2c44), STCP(0x6cb2a836, 0x4397ba32), STCP(0x6c964e82, 0x43c53c43), + STCP(0x6c79e1c1, 0x43f2b270), STCP(0x6c5d61f8, 0x44201cb2), STCP(0x6c40cf2b, 0x444d7aff), + STCP(0x6c24295f, 0x447acd50), STCP(0x6c07709b, 0x44a8139d), STCP(0x6beaa4e1, 0x44d54dde), + STCP(0x6bcdc639, 0x45027c0c), STCP(0x6bb0d4a6, 0x452f9e1e), STCP(0x6b93d02d, 0x455cb40c), + STCP(0x6b76b8d5, 0x4589bdce), STCP(0x6b598ea2, 0x45b6bb5d), STCP(0x6b3c5199, 0x45e3acb1), + STCP(0x6b1f01bf, 0x461091c1), STCP(0x6b019f19, 0x463d6a86), STCP(0x6ae429ad, 0x466a36f9), + STCP(0x6ac6a180, 0x4696f710), STCP(0x6aa90696, 0x46c3aac5), STCP(0x6a8b58f6, 0x46f0520f), + STCP(0x6a6d98a3, 0x471cece6), STCP(0x6a4fc5a5, 0x47497b44), STCP(0x6a31dfff, 0x4775fd1f), + STCP(0x6a13e7b7, 0x47a27270), STCP(0x69f5dcd2, 0x47cedb30), STCP(0x69d7bf56, 0x47fb3757), + STCP(0x69b98f47, 0x482786dc), STCP(0x699b4cac, 0x4853c9b8), STCP(0x697cf789, 0x487fffe3), + STCP(0x695e8fe4, 0x48ac2956), STCP(0x694015c2, 0x48d84609), STCP(0x69218928, 0x490455f3), + STCP(0x6902ea1c, 0x4930590e), STCP(0x68e438a3, 0x495c4f51), STCP(0x68c574c3, 0x498838b6), + STCP(0x68a69e80, 0x49b41533), STCP(0x6887b5e1, 0x49dfe4c2), STCP(0x6868baeb, 0x4a0ba75a), + STCP(0x6849ada3, 0x4a375cf4), STCP(0x682a8e0e, 0x4a630589), STCP(0x680b5c33, 0x4a8ea111), + STCP(0x67ec1816, 0x4aba2f83), STCP(0x67ccc1bd, 0x4ae5b0d9), STCP(0x67ad592e, 0x4b11250b), + STCP(0x678dde6e, 0x4b3c8c11), STCP(0x676e5182, 0x4b67e5e4), STCP(0x674eb270, 0x4b93327b), + STCP(0x672f013f, 0x4bbe71d0), STCP(0x670f3df2, 0x4be9a3db), STCP(0x66ef6890, 0x4c14c894), + STCP(0x66cf811f, 0x4c3fdff3), STCP(0x66af87a4, 0x4c6ae9f1), STCP(0x668f7c24, 0x4c95e687), + STCP(0x666f5ea5, 0x4cc0d5ad), STCP(0x664f2f2e, 0x4cebb75c), STCP(0x662eedc2, 0x4d168b8b), + STCP(0x660e9a69, 0x4d415233), STCP(0x65ee3528, 0x4d6c0b4e), STCP(0x65cdbe05, 0x4d96b6d3), + STCP(0x65ad3504, 0x4dc154bb), STCP(0x658c9a2d, 0x4debe4fe), STCP(0x656bed84, 0x4e166795), + STCP(0x654b2f0f, 0x4e40dc78), STCP(0x652a5ed5, 0x4e6b43a1), STCP(0x65097cda, 0x4e959d07), + STCP(0x64e88925, 0x4ebfe8a4), STCP(0x64c783bc, 0x4eea266f), STCP(0x64a66ca4, 0x4f145662), + STCP(0x648543e3, 0x4f3e7874), STCP(0x6464097e, 0x4f688c9f), STCP(0x6442bd7d, 0x4f9292db), + STCP(0x64215fe4, 0x4fbc8b21), STCP(0x63fff0b9, 0x4fe6756a), STCP(0x63de7003, 0x501051ad), + STCP(0x63bcddc6, 0x503a1fe4), STCP(0x639b3a0a, 0x5063e008), STCP(0x637984d4, 0x508d9211), + STCP(0x6357be29, 0x50b735f7), STCP(0x6335e610, 0x50e0cbb4), STCP(0x6313fc8f, 0x510a5340), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62cff56c, 0x515d37a8), STCP(0x62add7d5, 0x51869476), + STCP(0x628ba8ef, 0x51afe2f5), STCP(0x626968be, 0x51d92320), STCP(0x62471748, 0x520254ee), + STCP(0x6224b494, 0x522b7859), STCP(0x620240a8, 0x52548d58), STCP(0x61dfbb89, 0x527d93e6), + STCP(0x61bd253e, 0x52a68bfa), STCP(0x619a7dcd, 0x52cf758e), STCP(0x6177c53c, 0x52f8509a), + STCP(0x6154fb90, 0x53211d17), STCP(0x613220d1, 0x5349daff), STCP(0x610f3504, 0x53728a49), + STCP(0x60ec382f, 0x539b2aef), STCP(0x60c92a59, 0x53c3bce9), STCP(0x60a60b87, 0x53ec4032), + STCP(0x6082dbc0, 0x5414b4c0), STCP(0x605f9b0b, 0x543d1a8e), STCP(0x603c496c, 0x54657194), + STCP(0x6018e6ea, 0x548db9cb), STCP(0x5ff5738c, 0x54b5f32c), STCP(0x5fd1ef58, 0x54de1db0), + STCP(0x5fae5a54, 0x55063950), STCP(0x5f8ab486, 0x552e4605), STCP(0x5f66fdf4, 0x555643c8), + STCP(0x5f4336a6, 0x557e3291), STCP(0x5f1f5ea0, 0x55a6125b), STCP(0x5efb75ea, 0x55cde31d), + STCP(0x5ed77c89, 0x55f5a4d2), STCP(0x5eb37284, 0x561d5771), STCP(0x5e8f57e2, 0x5644faf4), + STCP(0x5e6b2ca8, 0x566c8f54), STCP(0x5e46f0dc, 0x5694148a), STCP(0x5e22a487, 0x56bb8a8f), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5dd9da55, 0x570a48eb), STCP(0x5db55c85, 0x57319134), + STCP(0x5d90ce44, 0x5758ca31), STCP(0x5d6c2f99, 0x577ff3da), STCP(0x5d478089, 0x57a70e29), + STCP(0x5d22c11b, 0x57ce1916), STCP(0x5cfdf156, 0x57f5149c), STCP(0x5cd91140, 0x581c00b3), + STCP(0x5cb420df, 0x5842dd54), STCP(0x5c8f203a, 0x5869aa78), STCP(0x5c6a0f58, 0x5890681a), + STCP(0x5c44ee3f, 0x58b71631), STCP(0x5c1fbcf5, 0x58ddb4b7), STCP(0x5bfa7b81, 0x590443a6), + STCP(0x5bd529ea, 0x592ac2f6), STCP(0x5bafc836, 0x595132a2), STCP(0x5b8a566b, 0x597792a1), + STCP(0x5b64d491, 0x599de2ed), STCP(0x5b3f42ae, 0x59c42380), STCP(0x5b19a0c7, 0x59ea5454), + STCP(0x5af3eee5, 0x5a107560), STCP(0x5ace2d0e, 0x5a36869f), STCP(0x5aa85b48, 0x5a5c8809), + STCP(0x5a827999, 0x5a827999), +}; +# endif + +/* + Sine windows + */ + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow20[10] = { +# else +const PWord16 SineWindow20[10] = { +# endif + WTCP(0x7fe6bcaf, 0x5067734), WTCP(0x7f1cde00, 0xf0b7727), WTCP(0x7d8a5f3f, 0x18f8b83c), + WTCP(0x7b31bbb1, 0x22be8f87), WTCP(0x7816a758, 0x2c4d9050), WTCP(0x743e0917, 0x3596a46c), + WTCP(0x6fadf2fb, 0x3e8b240e), WTCP(0x6a6d98a3, 0x471cece6), WTCP(0x648543e3, 0x4f3e7874), + WTCP(0x5dfe47ad, 0x56e2f15d), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow40[20] = { +# else +const PWord16 SineWindow40[20] = { +# endif + WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7e01b096, 0x16807e15), WTCP(0x7d06aa16, 0x1b6e7b7a), + WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x78ef678f, 0x29efc925), + WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x732af3a7, 0x37dc420c), + WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6bcdc639, 0x45027c0c), + WTCP(0x6902ea1d, 0x4930590f), WTCP(0x660e9a6a, 0x4d415234), WTCP(0x62f201ac, 0x5133cc94), + WTCP(0x5fae5a55, 0x55063951), WTCP(0x5c44ee40, 0x58b71632), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow60[30] = { +# else +const PWord16 SineWindow60[30] = { +# endif + WTCP(0x7ffd3153, 0x1aceb7c), WTCP(0x7fe6bcaf, 0x5067734), WTCP(0x7fb9d758, 0x85f2136), + WTCP(0x7f76892e, 0xbb65336), WTCP(0x7f1cde00, 0xf0b7727), WTCP(0x7eace589, 0x125df75b), + WTCP(0x7e26b370, 0x15ad3e9a), WTCP(0x7d8a5f3f, 0x18f8b83c), WTCP(0x7cd80464, 0x1c3fd045), + WTCP(0x7c0fc229, 0x1f81f37b), WTCP(0x7b31bbb1, 0x22be8f87), WTCP(0x7a3e17f1, 0x25f51307), + WTCP(0x793501a8, 0x2924edab), WTCP(0x7816a758, 0x2c4d9050), WTCP(0x76e33b3e, 0x2f6e6d15), + WTCP(0x759af34b, 0x3286f778), WTCP(0x743e0917, 0x3596a46c), WTCP(0x72ccb9da, 0x389cea71), + WTCP(0x7147465f, 0x3b9941b0), WTCP(0x6fadf2fb, 0x3e8b240e), WTCP(0x6e01077f, 0x41720d45), + WTCP(0x6c40cf2b, 0x444d7aff), WTCP(0x6a6d98a3, 0x471cece6), WTCP(0x6887b5e1, 0x49dfe4c2), + WTCP(0x668f7c24, 0x4c95e687), WTCP(0x648543e3, 0x4f3e7874), WTCP(0x626968be, 0x51d92320), + WTCP(0x603c496c, 0x54657194), WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5bafc836, 0x595132a2), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow80[40] = { +# else +const PWord16 SineWindow80[40] = { +# endif + WTCP(0x7ffe6bbf, 0x0141b1a5), WTCP(0x7ff1c9ef, 0x03c4f52f), WTCP(0x7fd8878e, 0x0647d97c), + WTCP(0x7fb2a71b, 0x08ca1f1b), WTCP(0x7f802c52, 0x0b4b86a8), WTCP(0x7f411c2f, 0x0dcbd0d5), + WTCP(0x7ef57cea, 0x104abe71), WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e38b017, 0x154387e6), + WTCP(0x7dc79529, 0x17bce621), WTCP(0x7d4a105d, 0x1a33ec9c), WTCP(0x7cc02e15, 0x1ca85d12), + WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7b8788ba, 0x2188841a), WTCP(0x7ad8e482, 0x23f3bf7e), + WTCP(0x7a1e2082, 0x265b6e8a), WTCP(0x79574f28, 0x28bf547b), WTCP(0x78848414, 0x2b1f34eb), + WTCP(0x77a5d413, 0x2d7ad3de), WTCP(0x76bb5521, 0x2fd1f5c1), WTCP(0x75c51e61, 0x32245f72), + WTCP(0x74c34820, 0x3471d647), WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x729d2409, 0x38fd032d), + WTCP(0x71790c7e, 0x3b3a4672), WTCP(0x7049c203, 0x3d71b14d), WTCP(0x6f0f6289, 0x3fa30bc1), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6c79e1c2, 0x43f2b271), WTCP(0x6b1f01c0, 0x461091c2), + WTCP(0x69b98f48, 0x482786dc), WTCP(0x6849ada3, 0x4a375cf5), WTCP(0x66cf8120, 0x4c3fdff4), + WTCP(0x654b2f10, 0x4e40dc79), WTCP(0x63bcddc7, 0x503a1fe5), WTCP(0x6224b495, 0x522b7859), + WTCP(0x6082dbc1, 0x5414b4c1), WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5d22c11c, 0x57ce1917), + WTCP(0x5b64d492, 0x599de2ee), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow120[60] = { +# else +const PWord16 SineWindow120[60] = { +# endif + WTCP(0x7fff4c54, 0x00d676eb), WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fee74a2, 0x0430238f), + WTCP(0x7fdd9dad, 0x05dcbcbe), WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fab1d3d, 0x093516d4), + WTCP(0x7f8975f9, 0x0ae0b22c), WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7f3560b9, 0x0e3667ad), + WTCP(0x7f02f66f, 0x0fe05c64), WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7e8d6d91, 0x13321c53), + WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7e01b096, 0x16807e15), WTCP(0x7db3860f, 0x18263d36), + WTCP(0x7d5fd801, 0x19caed29), WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7ca80038, 0x1d10d5c2), + WTCP(0x7c43de8e, 0x1eb1e9a7), WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7b6b45a5, 0x21eff528), + WTCP(0x7af6d7e6, 0x238cc85d), WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x79fdd35c, 0x26c1af22), + WTCP(0x7979477d, 0x28599eb0), WTCP(0x78ef678f, 0x29efc925), WTCP(0x7860399e, 0x2b841caf), + WTCP(0x77cbc3f2, 0x2d168792), WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76931bae, 0x30355cdd), + WTCP(0x75eef6ce, 0x31c1a43b), WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x74972f92, 0x34d3957e), + WTCP(0x73e39c49, 0x36591cea), WTCP(0x732af3a7, 0x37dc420c), WTCP(0x726d3dc6, 0x395cf3e9), + WTCP(0x71aa82f7, 0x3adb21a1), WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x701620f5, 0x3dcfadb0), + WTCP(0x6f448b7e, 0x3f45ead8), WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6d92c59b, 0x422a0154), + WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6ae429ae, 0x466a36f9), + WTCP(0x69f5dcd3, 0x47cedb31), WTCP(0x6902ea1d, 0x4930590f), WTCP(0x680b5c33, 0x4a8ea111), + WTCP(0x670f3df3, 0x4be9a3db), WTCP(0x660e9a6a, 0x4d415234), WTCP(0x65097cdb, 0x4e959d08), + WTCP(0x63fff0ba, 0x4fe6756a), WTCP(0x62f201ac, 0x5133cc94), WTCP(0x61dfbb8a, 0x527d93e6), + WTCP(0x60c92a5a, 0x53c3bcea), WTCP(0x5fae5a55, 0x55063951), WTCP(0x5e8f57e2, 0x5644faf4), + WTCP(0x5d6c2f99, 0x577ff3da), WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5b19a0c8, 0x59ea5454), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow160[80] = { +# else +const PWord16 SineWindow160[80] = { +# endif + WTCP(0x7fff9aef, 0x00a0d951), WTCP(0x7ffc726f, 0x01e287fc), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7feca851, 0x0465b9aa), WTCP(0x7fe00716, 0x05a72ccf), WTCP(0x7fd03e23, 0x06e87c3f), + WTCP(0x7fbd4dda, 0x0829a00c), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f8df93c, 0x0aab450d), + WTCP(0x7f719611, 0x0bebb66c), WTCP(0x7f520de6, 0x0d2bdc80), WTCP(0x7f2f6183, 0x0e6baf61), + WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7ee09f95, 0x10ea3bfd), WTCP(0x7eb48bfb, 0x1228e5f8), + WTCP(0x7e85580c, 0x13671d3d), WTCP(0x7e5304f2, 0x14a4d9f4), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7de50646, 0x171ec45c), WTCP(0x7da95d6c, 0x185ae269), WTCP(0x7d6a9ad5, 0x199666a0), + WTCP(0x7d28c00c, 0x1ad14938), WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7c9bc87a, 0x1d450a78), + WTCP(0x7c50af2b, 0x1e7dd9a4), WTCP(0x7c02849f, 0x1fb5e836), WTCP(0x7bb14ac5, 0x20ed2e7b), + WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7b05b13d, 0x2359436c), WTCP(0x7aab55ca, 0x248e02cb), + WTCP(0x7a4df380, 0x25c1db44), WTCP(0x79ed8cad, 0x26f4c53e), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x7923bb01, 0x2957af74), WTCP(0x78ba5524, 0x2a87a09d), WTCP(0x784df4b3, 0x2bb68522), + WTCP(0x77de9c5b, 0x2ce45589), WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76f70f05, 0x2f3c9c40), + WTCP(0x767edfbe, 0x306703bf), WTCP(0x7603c3fd, 0x31903982), WTCP(0x7585becb, 0x32b83634), + WTCP(0x7504d345, 0x33def287), WTCP(0x74810499, 0x35046736), WTCP(0x73fa5607, 0x36288d03), + WTCP(0x7370cae2, 0x374b5cb9), WTCP(0x72e4668f, 0x386ccf2a), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x71c3204c, 0x3aab7fb7), WTCP(0x712e457f, 0x3bc8afa5), WTCP(0x70969fca, 0x3ce465f3), + WTCP(0x6ffc32eb, 0x3dfe9ba1), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6ebf12ff, 0x402e694c), + WTCP(0x6e1c67c4, 0x4143f379), WTCP(0x6d770506, 0x4257e166), WTCP(0x6cceeed8, 0x436a2c45), + WTCP(0x6c242960, 0x447acd50), WTCP(0x6b76b8d6, 0x4589bdcf), WTCP(0x6ac6a180, 0x4696f710), + WTCP(0x6a13e7b8, 0x47a27271), WTCP(0x695e8fe5, 0x48ac2957), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x67ec1817, 0x4aba2f84), WTCP(0x672f013f, 0x4bbe71d1), WTCP(0x666f5ea6, 0x4cc0d5ae), + WTCP(0x65ad3505, 0x4dc154bb), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x64215fe5, 0x4fbc8b22), + WTCP(0x6357be2a, 0x50b735f8), WTCP(0x628ba8ef, 0x51afe2f6), WTCP(0x61bd253f, 0x52a68bfb), + WTCP(0x60ec3830, 0x539b2af0), WTCP(0x6018e6eb, 0x548db9cb), WTCP(0x5f4336a7, 0x557e3292), + WTCP(0x5e6b2ca8, 0x566c8f55), WTCP(0x5d90ce45, 0x5758ca31), WTCP(0x5cb420e0, 0x5842dd54), + WTCP(0x5bd529eb, 0x592ac2f7), WTCP(0x5af3eee6, 0x5a107561), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow180[90] = { +# else +const PWord16 SineWindow180[90] = { +# endif + WTCP(0x7fffb025, 0x008efa17), WTCP(0x7ffd3153, 0x01aceb7c), WTCP(0x7ff833bc, 0x02cad485), + WTCP(0x7ff0b779, 0x03e8af9e), WTCP(0x7fe6bcaf, 0x05067734), WTCP(0x7fda4390, 0x062425b6), + WTCP(0x7fcb4c5a, 0x0741b592), WTCP(0x7fb9d758, 0x085f2136), WTCP(0x7fa5e4e0, 0x097c6313), + WTCP(0x7f8f7558, 0x0a997597), WTCP(0x7f76892e, 0x0bb65336), WTCP(0x7f5b20de, 0x0cd2f660), + WTCP(0x7f3d3cf3, 0x0def5989), WTCP(0x7f1cde00, 0x0f0b7727), WTCP(0x7efa04a7, 0x102749ae), + WTCP(0x7ed4b197, 0x1142cb98), WTCP(0x7eace589, 0x125df75b), WTCP(0x7e82a145, 0x1378c774), + WTCP(0x7e55e59d, 0x1493365f), WTCP(0x7e26b370, 0x15ad3e9a), WTCP(0x7df50baa, 0x16c6daa6), + WTCP(0x7dc0ef43, 0x17e00505), WTCP(0x7d8a5f3f, 0x18f8b83c), WTCP(0x7d515cae, 0x1a10eed2), + WTCP(0x7d15e8ac, 0x1b28a351), WTCP(0x7cd80464, 0x1c3fd045), WTCP(0x7c97b108, 0x1d56703b), + WTCP(0x7c54efdb, 0x1e6c7dc7), WTCP(0x7c0fc229, 0x1f81f37b), WTCP(0x7bc8294c, 0x2096cbf0), + WTCP(0x7b7e26a9, 0x21ab01c0), WTCP(0x7b31bbb1, 0x22be8f87), WTCP(0x7ae2e9e3, 0x23d16fe8), + WTCP(0x7a91b2c6, 0x24e39d85), WTCP(0x7a3e17f1, 0x25f51307), WTCP(0x79e81b05, 0x2705cb19), + WTCP(0x798fbdaf, 0x2815c069), WTCP(0x793501a8, 0x2924edab), WTCP(0x78d7e8b5, 0x2a334d95), + WTCP(0x787874a6, 0x2b40dae2), WTCP(0x7816a758, 0x2c4d9050), WTCP(0x77b282b3, 0x2d5968a2), + WTCP(0x774c08aa, 0x2e645ea0), WTCP(0x76e33b3e, 0x2f6e6d15), WTCP(0x76781c79, 0x30778ed2), + WTCP(0x760aae72, 0x317fbeaa), WTCP(0x759af34b, 0x3286f778), WTCP(0x7528ed31, 0x338d341a), + WTCP(0x74b49e5f, 0x34926f74), WTCP(0x743e0917, 0x3596a46c), WTCP(0x73c52faa, 0x3699cdf1), + WTCP(0x734a1474, 0x379be6f6), WTCP(0x72ccb9da, 0x389cea71), WTCP(0x724d224e, 0x399cd362), + WTCP(0x71cb504d, 0x3a9b9cc9), WTCP(0x7147465f, 0x3b9941b0), WTCP(0x70c10717, 0x3c95bd25), + WTCP(0x70389513, 0x3d910a3c), WTCP(0x6fadf2fb, 0x3e8b240e), WTCP(0x6f212384, 0x3f8405bb), + WTCP(0x6e92296d, 0x407baa69), WTCP(0x6e01077f, 0x41720d45), WTCP(0x6d6dc08e, 0x42672980), + WTCP(0x6cd85779, 0x435afa54), WTCP(0x6c40cf2b, 0x444d7aff), WTCP(0x6ba72a97, 0x453ea6c7), + WTCP(0x6b0b6cbc, 0x462e78f8), WTCP(0x6a6d98a3, 0x471cece6), WTCP(0x69cdb161, 0x4809fdeb), + WTCP(0x692bba13, 0x48f5a767), WTCP(0x6887b5e1, 0x49dfe4c2), WTCP(0x67e1a7ff, 0x4ac8b16b), + WTCP(0x673993a8, 0x4bb008d8), WTCP(0x668f7c24, 0x4c95e687), WTCP(0x65e364c3, 0x4d7a45fd), + WTCP(0x653550e1, 0x4e5d22c5), WTCP(0x648543e3, 0x4f3e7874), WTCP(0x63d34136, 0x501e42a5), + WTCP(0x631f4c54, 0x50fc7cfa), WTCP(0x626968be, 0x51d92320), WTCP(0x61b19a00, 0x52b430c8), + WTCP(0x60f7e3b0, 0x538da1ae), WTCP(0x603c496c, 0x54657194), WTCP(0x5f7ecedd, 0x553b9c45), + WTCP(0x5ebf77b4, 0x56101d94), WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5d3b428b, 0x57b41383), + WTCP(0x5c766c1c, 0x58837ff3), WTCP(0x5bafc836, 0x595132a2), WTCP(0x5ae75ab8, 0x5a1d278c), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow240[120] = { +# else +const PWord16 SineWindow240[120] = { +# endif + WTCP(0x7fffd315, 0x006b3b9b), WTCP(0x7ffe6bbf, 0x0141b1a5), WTCP(0x7ffb9d15, 0x02182427), + WTCP(0x7ff76721, 0x02ee90c8), WTCP(0x7ff1c9ef, 0x03c4f52f), WTCP(0x7feac58d, 0x049b4f00), + WTCP(0x7fe25a0f, 0x05719be2), WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7fcd4e24, 0x071e0575), + WTCP(0x7fc0adf2, 0x07f41d72), WTCP(0x7fb2a71b, 0x08ca1f1b), WTCP(0x7fa339c5, 0x09a00817), + WTCP(0x7f92661d, 0x0a75d60e), WTCP(0x7f802c52, 0x0b4b86a8), WTCP(0x7f6c8c96, 0x0c21178c), + WTCP(0x7f578721, 0x0cf68662), WTCP(0x7f411c2f, 0x0dcbd0d5), WTCP(0x7f294bfd, 0x0ea0f48c), + WTCP(0x7f1016ce, 0x0f75ef33), WTCP(0x7ef57cea, 0x104abe71), WTCP(0x7ed97e9c, 0x111f5ff4), + WTCP(0x7ebc1c31, 0x11f3d164), WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e7d2c54, 0x139c1abf), + WTCP(0x7e5b9f93, 0x146fee03), WTCP(0x7e38b017, 0x154387e6), WTCP(0x7e145e42, 0x1616e618), + WTCP(0x7deeaa7a, 0x16ea0646), WTCP(0x7dc79529, 0x17bce621), WTCP(0x7d9f1ebd, 0x188f8357), + WTCP(0x7d7547a7, 0x1961db9b), WTCP(0x7d4a105d, 0x1a33ec9c), WTCP(0x7d1d7958, 0x1b05b40f), + WTCP(0x7cef8315, 0x1bd72fa4), WTCP(0x7cc02e15, 0x1ca85d12), WTCP(0x7c8f7ade, 0x1d793a0b), + WTCP(0x7c5d69f7, 0x1e49c447), WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7bf53153, 0x1fe9d75f), + WTCP(0x7bbf0aba, 0x20b95bac), WTCP(0x7b8788ba, 0x2188841a), WTCP(0x7b4eabf1, 0x22574e65), + WTCP(0x7b1474fd, 0x2325b847), WTCP(0x7ad8e482, 0x23f3bf7e), WTCP(0x7a9bfb27, 0x24c161c7), + WTCP(0x7a5db997, 0x258e9ce0), WTCP(0x7a1e2082, 0x265b6e8a), WTCP(0x79dd3098, 0x2727d486), + WTCP(0x799aea92, 0x27f3cc94), WTCP(0x79574f28, 0x28bf547b), WTCP(0x79125f19, 0x298a69fc), + WTCP(0x78cc1b26, 0x2a550adf), WTCP(0x78848414, 0x2b1f34eb), WTCP(0x783b9aad, 0x2be8e5e8), + WTCP(0x77f15fbc, 0x2cb21ba0), WTCP(0x77a5d413, 0x2d7ad3de), WTCP(0x7758f886, 0x2e430c6f), + WTCP(0x770acdec, 0x2f0ac320), WTCP(0x76bb5521, 0x2fd1f5c1), WTCP(0x766a8f04, 0x3098a223), + WTCP(0x76187c77, 0x315ec617), WTCP(0x75c51e61, 0x32245f72), WTCP(0x757075ac, 0x32e96c09), + WTCP(0x751a8346, 0x33ade9b3), WTCP(0x74c34820, 0x3471d647), WTCP(0x746ac52f, 0x35352fa1), + WTCP(0x7410fb6b, 0x35f7f39c), WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x73599760, 0x377bb2e9), + WTCP(0x72fbff1b, 0x383ca9fb), WTCP(0x729d2409, 0x38fd032d), WTCP(0x723d0734, 0x39bcbc63), + WTCP(0x71dba9ab, 0x3a7bd382), WTCP(0x71790c7e, 0x3b3a4672), WTCP(0x711530c2, 0x3bf8131c), + WTCP(0x70b01790, 0x3cb5376b), WTCP(0x7049c203, 0x3d71b14d), WTCP(0x6fe2313c, 0x3e2d7eb1), + WTCP(0x6f79665b, 0x3ee89d86), WTCP(0x6f0f6289, 0x3fa30bc1), WTCP(0x6ea426ed, 0x405cc754), + WTCP(0x6e37b4b6, 0x4115ce38), WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6d5b313b, 0x4285b5d4), + WTCP(0x6ceb2261, 0x433c9283), WTCP(0x6c79e1c2, 0x43f2b271), WTCP(0x6c07709b, 0x44a8139e), + WTCP(0x6b93d02e, 0x455cb40c), WTCP(0x6b1f01c0, 0x461091c2), WTCP(0x6aa90697, 0x46c3aac5), + WTCP(0x6a31e000, 0x4775fd1f), WTCP(0x69b98f48, 0x482786dc), WTCP(0x694015c3, 0x48d84609), + WTCP(0x68c574c4, 0x498838b6), WTCP(0x6849ada3, 0x4a375cf5), WTCP(0x67ccc1be, 0x4ae5b0da), + WTCP(0x674eb271, 0x4b93327c), WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x664f2f2e, 0x4cebb75c), + WTCP(0x65cdbe05, 0x4d96b6d3), WTCP(0x654b2f10, 0x4e40dc79), WTCP(0x64c783bd, 0x4eea2670), + WTCP(0x6442bd7e, 0x4f9292dc), WTCP(0x63bcddc7, 0x503a1fe5), WTCP(0x6335e611, 0x50e0cbb4), + WTCP(0x62add7d6, 0x51869476), WTCP(0x6224b495, 0x522b7859), WTCP(0x619a7dce, 0x52cf758f), + WTCP(0x610f3505, 0x53728a4a), WTCP(0x6082dbc1, 0x5414b4c1), WTCP(0x5ff5738d, 0x54b5f32c), + WTCP(0x5f66fdf5, 0x555643c8), WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5e46f0dd, 0x5694148b), + WTCP(0x5db55c86, 0x57319135), WTCP(0x5d22c11c, 0x57ce1917), WTCP(0x5c8f203b, 0x5869aa79), + WTCP(0x5bfa7b82, 0x590443a7), WTCP(0x5b64d492, 0x599de2ee), WTCP(0x5ace2d0f, 0x5a36869f), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow320[160] = { +# else +const PWord16 SineWindow320[160] = { +# endif + WTCP(0x7fffe6bc, 0x00506cb9), WTCP(0x7fff1c9b, 0x00f145ab), WTCP(0x7ffd885a, 0x01921d20), + WTCP(0x7ffb29fd, 0x0232f21a), WTCP(0x7ff80186, 0x02d3c39b), WTCP(0x7ff40efa, 0x037490a5), + WTCP(0x7fef5260, 0x0415583b), WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fe37b22, 0x0556d30f), + WTCP(0x7fdc608f, 0x05f78453), WTCP(0x7fd47c14, 0x06982c2b), WTCP(0x7fcbcdbc, 0x0738c998), + WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7fb813b0, 0x0879e140), WTCP(0x7fad081b, 0x091a597e), + WTCP(0x7fa132e8, 0x09bac35d), WTCP(0x7f949429, 0x0a5b1dde), WTCP(0x7f872bf3, 0x0afb6805), + WTCP(0x7f78fa5b, 0x0b9ba0d5), WTCP(0x7f69ff76, 0x0c3bc74f), WTCP(0x7f5a3b5e, 0x0cdbda79), + WTCP(0x7f49ae2a, 0x0d7bd954), WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7f2638db, 0x0ebb962c), + WTCP(0x7f1350f8, 0x0f5b5231), WTCP(0x7effa069, 0x0ffaf5f6), WTCP(0x7eeb274d, 0x109a807e), + WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7ebfdbf5, 0x11d945eb), WTCP(0x7ea909fc, 0x12787ed8), + WTCP(0x7e917000, 0x13179a9b), WTCP(0x7e790e25, 0x13b69836), WTCP(0x7e5fe493, 0x145576b1), + WTCP(0x7e45f371, 0x14f43510), WTCP(0x7e2b3ae8, 0x1592d257), WTCP(0x7e0fbb22, 0x16314d8e), + WTCP(0x7df3744b, 0x16cfa5b9), WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7db8921c, 0x180be904), + WTCP(0x7d99f721, 0x18a9d231), WTCP(0x7d7a95cf, 0x1947946c), WTCP(0x7d5a6e57, 0x19e52ebb), + WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7d17cdc2, 0x1b1fe7b3), WTCP(0x7cf5550e, 0x1bbd046c), + WTCP(0x7cd21707, 0x1c59f557), WTCP(0x7cae13e4, 0x1cf6b97c), WTCP(0x7c894bde, 0x1d934fe5), + WTCP(0x7c63bf2f, 0x1e2fb79a), WTCP(0x7c3d6e13, 0x1ecbefa4), WTCP(0x7c1658c5, 0x1f67f70b), + WTCP(0x7bee7f85, 0x2003ccdb), WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7b9c8226, 0x213adfda), + WTCP(0x7b725e8a, 0x21d61b1e), WTCP(0x7b4777fe, 0x227120f3), WTCP(0x7b1bcec4, 0x230bf065), + WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7ac23561, 0x2440e84d), WTCP(0x7a9445c5, 0x24db0edb), + WTCP(0x7a659496, 0x2574fb36), WTCP(0x7a362220, 0x260eac6a), WTCP(0x7a05eead, 0x26a82186), + WTCP(0x79d4fa89, 0x27415996), WTCP(0x79a34602, 0x27da53a9), WTCP(0x7970d165, 0x28730ecd), + WTCP(0x793d9d03, 0x290b8a12), WTCP(0x7909a92d, 0x29a3c485), WTCP(0x78d4f634, 0x2a3bbd37), + WTCP(0x789f846b, 0x2ad37338), WTCP(0x78695428, 0x2b6ae598), WTCP(0x783265c0, 0x2c021369), + WTCP(0x77fab989, 0x2c98fbba), WTCP(0x77c24fdb, 0x2d2f9d9f), WTCP(0x77892910, 0x2dc5f829), + WTCP(0x774f4581, 0x2e5c0a6b), WTCP(0x7714a58b, 0x2ef1d377), WTCP(0x76d94989, 0x2f875262), + WTCP(0x769d31d9, 0x301c863f), WTCP(0x76605edb, 0x30b16e23), WTCP(0x7622d0ef, 0x31460922), + WTCP(0x75e48874, 0x31da5651), WTCP(0x75a585cf, 0x326e54c7), WTCP(0x7565c962, 0x3302039b), + WTCP(0x75255392, 0x339561e1), WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74a23d62, 0x34bb2927), + WTCP(0x745f9dd1, 0x354d9057), WTCP(0x741c467b, 0x35dfa35a), WTCP(0x73d837ca, 0x3671614b), + WTCP(0x7393722a, 0x3702c942), WTCP(0x734df607, 0x3793da5b), WTCP(0x7307c3d0, 0x382493b0), + WTCP(0x72c0dbf3, 0x38b4f45d), WTCP(0x72793edf, 0x3944fb7e), WTCP(0x7230ed07, 0x39d4a82f), + WTCP(0x71e7e6dc, 0x3a63f98d), WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x7153bf5d, 0x3b8186ca), + WTCP(0x71089ef2, 0x3c0fc0e6), WTCP(0x70bccc09, 0x3c9d9c28), WTCP(0x70704718, 0x3d2b17b3), + WTCP(0x7023109a, 0x3db832a6), WTCP(0x6fd52907, 0x3e44ec22), WTCP(0x6f8690db, 0x3ed14349), + WTCP(0x6f374891, 0x3f5d373e), WTCP(0x6ee750a8, 0x3fe8c724), WTCP(0x6e96a99d, 0x4073f21d), + WTCP(0x6e4553ef, 0x40feb74f), WTCP(0x6df35020, 0x418915de), WTCP(0x6da09eb1, 0x42130cf0), + WTCP(0x6d4d4023, 0x429c9bab), WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6ca47dbf, 0x43ae7cb7), + WTCP(0x6c4f1af2, 0x4436cd58), WTCP(0x6bf90d1d, 0x44beb240), WTCP(0x6ba254c7, 0x45462a9a), + WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6af2e6bc, 0x4653d24b), WTCP(0x6a9a321d, 0x46d9fff8), + WTCP(0x6a40d527, 0x475fbdc3), WTCP(0x69e6d067, 0x47e50ad8), WTCP(0x698c246c, 0x4869e665), + WTCP(0x6930d1c4, 0x48ee4f98), WTCP(0x68d4d900, 0x497245a1), WTCP(0x68783ab1, 0x49f5c7ae), + WTCP(0x681af76a, 0x4a78d4f0), WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x675e843e, 0x4b7d8dd8), + WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x669f8425, 0x4c8069ea), WTCP(0x663f10b7, 0x4d012324), + WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x657c4613, 0x4e012800), WTCP(0x6519f010, 0x4e80720e), + WTCP(0x64b6fa66, 0x4eff4025), WTCP(0x645365b2, 0x4f7d917c), WTCP(0x63ef3290, 0x4ffb654d), + WTCP(0x638a619e, 0x5078bad1), WTCP(0x6324f37d, 0x50f59141), WTCP(0x62bee8cc, 0x5171e7d9), + WTCP(0x6258422c, 0x51edbdd4), WTCP(0x61f1003f, 0x5269126e), WTCP(0x618923a9, 0x52e3e4e6), + WTCP(0x6120ad0d, 0x535e3479), WTCP(0x60b79d10, 0x53d80065), WTCP(0x604df459, 0x545147eb), + WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5f78db56, 0x554246c6), WTCP(0x5f0d6c5b, 0x55b9fc9e), + WTCP(0x5ea16747, 0x56312b17), WTCP(0x5e34ccc3, 0x56a7d174), WTCP(0x5dc79d7c, 0x571deefa), + WTCP(0x5d59da1e, 0x579382ee), WTCP(0x5ceb8355, 0x58088c96), WTCP(0x5c7c99d1, 0x587d0b3b), + WTCP(0x5c0d1e41, 0x58f0fe23), WTCP(0x5b9d1154, 0x59646498), WTCP(0x5b2c73bb, 0x59d73de3), + WTCP(0x5abb4629, 0x5a498950), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow360[180] = { +# else +const PWord16 SineWindow360[180] = { +# endif + WTCP(0x7fffec08, 0x00477d17), WTCP(0x7fff4c53, 0x00d676eb), WTCP(0x7ffe0cea, 0x01656fb4), + WTCP(0x7ffc2dcf, 0x01f466bf), WTCP(0x7ff9af03, 0x02835b59), WTCP(0x7ff6908a, 0x03124cd1), + WTCP(0x7ff2d268, 0x03a13a74), WTCP(0x7fee74a1, 0x0430238f), WTCP(0x7fe9773c, 0x04bf0771), + WTCP(0x7fe3da3d, 0x054de566), WTCP(0x7fdd9dac, 0x05dcbcbe), WTCP(0x7fd6c192, 0x066b8cc5), + WTCP(0x7fcf45f6, 0x06fa54c9), WTCP(0x7fc72ae1, 0x07891418), WTCP(0x7fbe705f, 0x0817ca01), + WTCP(0x7fb51679, 0x08a675d0), WTCP(0x7fab1d3c, 0x093516d4), WTCP(0x7fa084b4, 0x09c3ac5c), + WTCP(0x7f954cee, 0x0a5235b4), WTCP(0x7f8975f8, 0x0ae0b22c), WTCP(0x7f7cffe1, 0x0b6f2112), + WTCP(0x7f6feab8, 0x0bfd81b3), WTCP(0x7f62368e, 0x0c8bd35e), WTCP(0x7f53e374, 0x0d1a1562), + WTCP(0x7f44f17c, 0x0da8470d), WTCP(0x7f3560b8, 0x0e3667ad), WTCP(0x7f25313c, 0x0ec47692), + WTCP(0x7f14631c, 0x0f52730a), WTCP(0x7f02f66e, 0x0fe05c64), WTCP(0x7ef0eb45, 0x106e31ef), + WTCP(0x7ede41ba, 0x10fbf2fa), WTCP(0x7ecaf9e4, 0x11899ed3), WTCP(0x7eb713da, 0x121734cb), + WTCP(0x7ea28fb5, 0x12a4b431), WTCP(0x7e8d6d90, 0x13321c53), WTCP(0x7e77ad84, 0x13bf6c82), + WTCP(0x7e614fac, 0x144ca40e), WTCP(0x7e4a5425, 0x14d9c245), WTCP(0x7e32bb0b, 0x1566c679), + WTCP(0x7e1a847b, 0x15f3aff8), WTCP(0x7e01b095, 0x16807e14), WTCP(0x7de83f76, 0x170d301d), + WTCP(0x7dce313e, 0x1799c562), WTCP(0x7db3860e, 0x18263d35), WTCP(0x7d983e08, 0x18b296e7), + WTCP(0x7d7c594d, 0x193ed1c8), WTCP(0x7d5fd800, 0x19caed28), WTCP(0x7d42ba45, 0x1a56e85b), + WTCP(0x7d25003f, 0x1ae2c2b0), WTCP(0x7d06aa15, 0x1b6e7b7a), WTCP(0x7ce7b7ec, 0x1bfa1209), + WTCP(0x7cc829ea, 0x1c8585b0), WTCP(0x7ca80037, 0x1d10d5c1), WTCP(0x7c873afb, 0x1d9c018f), + WTCP(0x7c65da60, 0x1e27086a), WTCP(0x7c43de8d, 0x1eb1e9a6), WTCP(0x7c2147af, 0x1f3ca496), + WTCP(0x7bfe15f0, 0x1fc7388d), WTCP(0x7bda497c, 0x2051a4dd), WTCP(0x7bb5e27f, 0x20dbe8da), + WTCP(0x7b90e128, 0x216603d7), WTCP(0x7b6b45a4, 0x21eff528), WTCP(0x7b451022, 0x2279bc21), + WTCP(0x7b1e40d3, 0x23035817), WTCP(0x7af6d7e5, 0x238cc85c), WTCP(0x7aced58b, 0x24160c47), + WTCP(0x7aa639f7, 0x249f232b), WTCP(0x7a7d055a, 0x25280c5d), WTCP(0x7a5337e9, 0x25b0c734), + WTCP(0x7a28d1d8, 0x26395303), WTCP(0x79fdd35b, 0x26c1af21), WTCP(0x79d23ca9, 0x2749dae4), + WTCP(0x79a60df7, 0x27d1d5a2), WTCP(0x7979477c, 0x28599eb0), WTCP(0x794be972, 0x28e13566), + WTCP(0x791df40f, 0x2968991b), WTCP(0x78ef678e, 0x29efc925), WTCP(0x78c04429, 0x2a76c4dc), + WTCP(0x78908a1a, 0x2afd8b97), WTCP(0x7860399d, 0x2b841caf), WTCP(0x782f52ef, 0x2c0a777b), + WTCP(0x77fdd64b, 0x2c909b54), WTCP(0x77cbc3f1, 0x2d168792), WTCP(0x77991c1e, 0x2d9c3b8e), + WTCP(0x7765df12, 0x2e21b6a2), WTCP(0x77320d0c, 0x2ea6f826), WTCP(0x76fda64e, 0x2f2bff76), + WTCP(0x76c8ab18, 0x2fb0cbea), WTCP(0x76931bae, 0x30355cdc), WTCP(0x765cf850, 0x30b9b1a9), + WTCP(0x76264144, 0x313dc9aa), WTCP(0x75eef6ce, 0x31c1a43a), WTCP(0x75b71931, 0x324540b6), + WTCP(0x757ea8b5, 0x32c89e78), WTCP(0x7545a59f, 0x334bbcde), WTCP(0x750c1038, 0x33ce9b42), + WTCP(0x74d1e8c5, 0x34513903), WTCP(0x74972f91, 0x34d3957e), WTCP(0x745be4e4, 0x3555b00e), + WTCP(0x74200908, 0x35d78813), WTCP(0x73e39c48, 0x36591cea), WTCP(0x73a69ef0, 0x36da6df1), + WTCP(0x7369114b, 0x375b7a87), WTCP(0x732af3a6, 0x37dc420c), WTCP(0x72ec4650, 0x385cc3de), + WTCP(0x72ad0995, 0x38dcff5d), WTCP(0x726d3dc5, 0x395cf3e9), WTCP(0x722ce330, 0x39dca0e2), + WTCP(0x71ebfa25, 0x3a5c05aa), WTCP(0x71aa82f6, 0x3adb21a0), WTCP(0x71687df5, 0x3b59f428), + WTCP(0x7125eb74, 0x3bd87ca1), WTCP(0x70e2cbc5, 0x3c56ba70), WTCP(0x709f1f3d, 0x3cd4acf5), + WTCP(0x705ae630, 0x3d525394), WTCP(0x701620f4, 0x3dcfadaf), WTCP(0x6fd0cfdd, 0x3e4cbaac), + WTCP(0x6f8af343, 0x3ec979ed), WTCP(0x6f448b7d, 0x3f45ead7), WTCP(0x6efd98e2, 0x3fc20ccf), + WTCP(0x6eb61bcb, 0x403ddf39), WTCP(0x6e6e1492, 0x40b9617c), WTCP(0x6e25838f, 0x413492fd), + WTCP(0x6ddc691e, 0x41af7323), WTCP(0x6d92c59a, 0x422a0154), WTCP(0x6d48995f, 0x42a43cf7), + WTCP(0x6cfde4c9, 0x431e2573), WTCP(0x6cb2a836, 0x4397ba32), WTCP(0x6c66e403, 0x4410fa9a), + WTCP(0x6c1a988f, 0x4489e615), WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6b806d61, 0x457abbe8), + WTCP(0x6b328e67, 0x45f2a513), WTCP(0x6ae429ad, 0x466a36f9), WTCP(0x6a953f94, 0x46e17102), + WTCP(0x6a45d080, 0x4758529c), WTCP(0x69f5dcd2, 0x47cedb30), WTCP(0x69a564ef, 0x48450a2d), + WTCP(0x6954693b, 0x48badefd), WTCP(0x6902ea1c, 0x4930590e), WTCP(0x68b0e7f6, 0x49a577ce), + WTCP(0x685e6331, 0x4a1a3aaa), WTCP(0x680b5c33, 0x4a8ea111), WTCP(0x67b7d363, 0x4b02aa71), + WTCP(0x6763c92b, 0x4b76563a), WTCP(0x670f3df2, 0x4be9a3db), WTCP(0x66ba3223, 0x4c5c92c4), + WTCP(0x6664a627, 0x4ccf2267), WTCP(0x660e9a69, 0x4d415233), WTCP(0x65b80f55, 0x4db3219c), + WTCP(0x65610557, 0x4e249011), WTCP(0x65097cda, 0x4e959d07), WTCP(0x64b1764d, 0x4f0647f0), + WTCP(0x6458f21d, 0x4f769040), WTCP(0x63fff0b9, 0x4fe6756a), WTCP(0x63a6728f, 0x5055f6e2), + WTCP(0x634c7810, 0x50c5141e), WTCP(0x62f201ac, 0x5133cc94), WTCP(0x62970fd2, 0x51a21fb7), + WTCP(0x623ba2f6, 0x52100d01), WTCP(0x61dfbb89, 0x527d93e6), WTCP(0x618359fd, 0x52eab3de), + WTCP(0x61267ec7, 0x53576c62), WTCP(0x60c92a59, 0x53c3bce9), WTCP(0x606b5d28, 0x542fa4ed), + WTCP(0x600d17aa, 0x549b23e7), WTCP(0x5fae5a54, 0x55063950), WTCP(0x5f4f259c, 0x5570e4a3), + WTCP(0x5eef79f8, 0x55db255b), WTCP(0x5e8f57e2, 0x5644faf4), WTCP(0x5e2ebfcf, 0x56ae64e9), + WTCP(0x5dcdb239, 0x571762b6), WTCP(0x5d6c2f99, 0x577ff3da), WTCP(0x5d0a3868, 0x57e817d1), + WTCP(0x5ca7cd21, 0x584fce19), WTCP(0x5c44ee3f, 0x58b71631), WTCP(0x5be19c3c, 0x591def98), + WTCP(0x5b7dd796, 0x598459ce), WTCP(0x5b19a0c7, 0x59ea5454), WTCP(0x5ab4f84f, 0x5a4fdea9), +}; + +# ifdef ENABLE_HR_MODE +const PWord32 SineWindow480[240] = { +# else +const PWord16 SineWindow480[240] = { +# endif + WTCP(0x7ffff4c5, 0x00359dd2), WTCP(0x7fff9aef, 0x00a0d951), WTCP(0x7ffee744, 0x010c1460), + WTCP(0x7ffdd9c4, 0x01774eb2), WTCP(0x7ffc726f, 0x01e287fc), WTCP(0x7ffab147, 0x024dbff4), + WTCP(0x7ff8964d, 0x02b8f64e), WTCP(0x7ff62182, 0x03242abf), WTCP(0x7ff352e8, 0x038f5cfb), + WTCP(0x7ff02a82, 0x03fa8cb8), WTCP(0x7feca851, 0x0465b9aa), WTCP(0x7fe8cc57, 0x04d0e386), + WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fe00716, 0x05a72ccf), WTCP(0x7fdb1dd5, 0x06124ba5), + WTCP(0x7fd5dad8, 0x067d6639), WTCP(0x7fd03e23, 0x06e87c3f), WTCP(0x7fca47b9, 0x07538d6b), + WTCP(0x7fc3f7a0, 0x07be9973), WTCP(0x7fbd4dda, 0x0829a00c), WTCP(0x7fb64a6e, 0x0894a0ea), + WTCP(0x7faeed5f, 0x08ff9bc2), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f9f2671, 0x09d57e35), + WTCP(0x7f96bc9c, 0x0a40653a), WTCP(0x7f8df93c, 0x0aab450d), WTCP(0x7f84dc55, 0x0b161d63), + WTCP(0x7f7b65ef, 0x0b80edf1), WTCP(0x7f719611, 0x0bebb66c), WTCP(0x7f676cc0, 0x0c56768a), + WTCP(0x7f5cea05, 0x0cc12dff), WTCP(0x7f520de6, 0x0d2bdc80), WTCP(0x7f46d86c, 0x0d9681c2), + WTCP(0x7f3b499d, 0x0e011d7c), WTCP(0x7f2f6183, 0x0e6baf61), WTCP(0x7f232026, 0x0ed63727), + WTCP(0x7f16858e, 0x0f40b483), WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7efc44d0, 0x10158ed4), + WTCP(0x7eee9ebe, 0x107feb33), WTCP(0x7ee09f95, 0x10ea3bfd), WTCP(0x7ed24761, 0x115480e9), + WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7eb48bfb, 0x1228e5f8), WTCP(0x7ea528e0, 0x12930586), + WTCP(0x7e956ce1, 0x12fd180b), WTCP(0x7e85580c, 0x13671d3d), WTCP(0x7e74ea6a, 0x13d114d0), + WTCP(0x7e642408, 0x143afe7b), WTCP(0x7e5304f2, 0x14a4d9f4), WTCP(0x7e418d32, 0x150ea6ef), + WTCP(0x7e2fbcd6, 0x15786522), WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7e0b127a, 0x164bb40b), + WTCP(0x7df83895, 0x16b5442b), WTCP(0x7de50646, 0x171ec45c), WTCP(0x7dd17b9c, 0x17883452), + WTCP(0x7dbd98a4, 0x17f193c5), WTCP(0x7da95d6c, 0x185ae269), WTCP(0x7d94ca03, 0x18c41ff6), + WTCP(0x7d7fde76, 0x192d4c21), WTCP(0x7d6a9ad5, 0x199666a0), WTCP(0x7d54ff2e, 0x19ff6f2a), + WTCP(0x7d3f0b90, 0x1a686575), WTCP(0x7d28c00c, 0x1ad14938), WTCP(0x7d121cb0, 0x1b3a1a28), + WTCP(0x7cfb218c, 0x1ba2d7fc), WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7ccc2430, 0x1c74192a), + WTCP(0x7cb42217, 0x1cdc9bf2), WTCP(0x7c9bc87a, 0x1d450a78), WTCP(0x7c831767, 0x1dad6473), + WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7c50af2b, 0x1e7dd9a4), WTCP(0x7c36f824, 0x1ee5f447), + WTCP(0x7c1ce9ef, 0x1f4df93a), WTCP(0x7c02849f, 0x1fb5e836), WTCP(0x7be7c847, 0x201dc0ef), + WTCP(0x7bccb4f8, 0x2085831f), WTCP(0x7bb14ac5, 0x20ed2e7b), WTCP(0x7b9589c3, 0x2154c2bb), + WTCP(0x7b797205, 0x21bc3f97), WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7b403ea2, 0x228af1fe), + WTCP(0x7b232325, 0x22f226f8), WTCP(0x7b05b13d, 0x2359436c), WTCP(0x7ae7e8fc, 0x23c04710), + WTCP(0x7ac9ca7a, 0x2427319d), WTCP(0x7aab55ca, 0x248e02cb), WTCP(0x7a8c8b01, 0x24f4ba50), + WTCP(0x7a6d6a37, 0x255b57e6), WTCP(0x7a4df380, 0x25c1db44), WTCP(0x7a2e26f2, 0x26284422), + WTCP(0x7a0e04a4, 0x268e9238), WTCP(0x79ed8cad, 0x26f4c53e), WTCP(0x79ccbf22, 0x275adcee), + WTCP(0x79ab9c1c, 0x27c0d8fe), WTCP(0x798a23b1, 0x2826b928), WTCP(0x796855f9, 0x288c7d24), + WTCP(0x7946330c, 0x28f224ab), WTCP(0x7923bb01, 0x2957af74), WTCP(0x7900edf2, 0x29bd1d3a), + WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78ba5524, 0x2a87a09d), WTCP(0x78968998, 0x2aecb5ac), + WTCP(0x7872696a, 0x2b51ac9a), WTCP(0x784df4b3, 0x2bb68522), WTCP(0x78292b8d, 0x2c1b3efb), + WTCP(0x78040e12, 0x2c7fd9e0), WTCP(0x77de9c5b, 0x2ce45589), WTCP(0x77b8d683, 0x2d48b1b1), + WTCP(0x7792bca5, 0x2dacee11), WTCP(0x776c4edb, 0x2e110a62), WTCP(0x77458d40, 0x2e75065e), + WTCP(0x771e77f0, 0x2ed8e1c0), WTCP(0x76f70f05, 0x2f3c9c40), WTCP(0x76cf529c, 0x2fa03599), + WTCP(0x76a742d1, 0x3003ad85), WTCP(0x767edfbe, 0x306703bf), WTCP(0x76562982, 0x30ca3800), + WTCP(0x762d2038, 0x312d4a03), WTCP(0x7603c3fd, 0x31903982), WTCP(0x75da14ef, 0x31f30638), + WTCP(0x75b01329, 0x3255afe0), WTCP(0x7585becb, 0x32b83634), WTCP(0x755b17f2, 0x331a98ef), + WTCP(0x75301ebb, 0x337cd7cd), WTCP(0x7504d345, 0x33def287), WTCP(0x74d935ae, 0x3440e8da), + WTCP(0x74ad4615, 0x34a2ba81), WTCP(0x74810499, 0x35046736), WTCP(0x74547158, 0x3565eeb6), + WTCP(0x74278c72, 0x35c750bc), WTCP(0x73fa5607, 0x36288d03), WTCP(0x73ccce36, 0x3689a348), + WTCP(0x739ef51f, 0x36ea9346), WTCP(0x7370cae2, 0x374b5cb9), WTCP(0x73424fa0, 0x37abff5d), + WTCP(0x73138379, 0x380c7aee), WTCP(0x72e4668f, 0x386ccf2a), WTCP(0x72b4f902, 0x38ccfbcb), + WTCP(0x72853af3, 0x392d008f), WTCP(0x72552c85, 0x398cdd32), WTCP(0x7224cdd8, 0x39ec9172), + WTCP(0x71f41f0f, 0x3a4c1d09), WTCP(0x71c3204c, 0x3aab7fb7), WTCP(0x7191d1b1, 0x3b0ab937), + WTCP(0x71603361, 0x3b69c947), WTCP(0x712e457f, 0x3bc8afa5), WTCP(0x70fc082d, 0x3c276c0d), + WTCP(0x70c97b90, 0x3c85fe3d), WTCP(0x70969fca, 0x3ce465f3), WTCP(0x706374ff, 0x3d42a2ec), + WTCP(0x702ffb54, 0x3da0b4e7), WTCP(0x6ffc32eb, 0x3dfe9ba1), WTCP(0x6fc81bea, 0x3e5c56d8), + WTCP(0x6f93b676, 0x3eb9e64b), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6f2a00c4, 0x3f7480dd), + WTCP(0x6ef4b0d1, 0x3fd18b7a), WTCP(0x6ebf12ff, 0x402e694c), WTCP(0x6e892772, 0x408b1a12), + WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6e1c67c4, 0x4143f379), WTCP(0x6de593ee, 0x41a01b97), + WTCP(0x6dae72f7, 0x41fc15a6), WTCP(0x6d770506, 0x4257e166), WTCP(0x6d3f4a40, 0x42b37e96), + WTCP(0x6d0742cf, 0x430eecf6), WTCP(0x6cceeed8, 0x436a2c45), WTCP(0x6c964e83, 0x43c53c44), + WTCP(0x6c5d61f9, 0x44201cb2), WTCP(0x6c242960, 0x447acd50), WTCP(0x6beaa4e2, 0x44d54ddf), + WTCP(0x6bb0d4a7, 0x452f9e1e), WTCP(0x6b76b8d6, 0x4589bdcf), WTCP(0x6b3c519a, 0x45e3acb1), + WTCP(0x6b019f1a, 0x463d6a87), WTCP(0x6ac6a180, 0x4696f710), WTCP(0x6a8b58f6, 0x46f0520f), + WTCP(0x6a4fc5a6, 0x47497b44), WTCP(0x6a13e7b8, 0x47a27271), WTCP(0x69d7bf57, 0x47fb3757), + WTCP(0x699b4cad, 0x4853c9b9), WTCP(0x695e8fe5, 0x48ac2957), WTCP(0x69218929, 0x490455f4), + WTCP(0x68e438a4, 0x495c4f52), WTCP(0x68a69e81, 0x49b41533), WTCP(0x6868baec, 0x4a0ba75b), + WTCP(0x682a8e0f, 0x4a63058a), WTCP(0x67ec1817, 0x4aba2f84), WTCP(0x67ad592f, 0x4b11250c), + WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x672f013f, 0x4bbe71d1), WTCP(0x66ef6891, 0x4c14c894), + WTCP(0x66af87a4, 0x4c6ae9f2), WTCP(0x666f5ea6, 0x4cc0d5ae), WTCP(0x662eedc3, 0x4d168b8b), + WTCP(0x65ee3529, 0x4d6c0b4e), WTCP(0x65ad3505, 0x4dc154bb), WTCP(0x656bed84, 0x4e166795), + WTCP(0x652a5ed6, 0x4e6b43a2), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x64a66ca5, 0x4f145662), + WTCP(0x6464097f, 0x4f688ca0), WTCP(0x64215fe5, 0x4fbc8b22), WTCP(0x63de7003, 0x501051ae), + WTCP(0x639b3a0b, 0x5063e008), WTCP(0x6357be2a, 0x50b735f8), WTCP(0x6313fc90, 0x510a5340), + WTCP(0x62cff56c, 0x515d37a9), WTCP(0x628ba8ef, 0x51afe2f6), WTCP(0x62471749, 0x520254ef), + WTCP(0x620240a8, 0x52548d59), WTCP(0x61bd253f, 0x52a68bfb), WTCP(0x6177c53c, 0x52f8509b), + WTCP(0x613220d2, 0x5349daff), WTCP(0x60ec3830, 0x539b2af0), WTCP(0x60a60b88, 0x53ec4032), + WTCP(0x605f9b0b, 0x543d1a8e), WTCP(0x6018e6eb, 0x548db9cb), WTCP(0x5fd1ef59, 0x54de1db1), + WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5f4336a7, 0x557e3292), WTCP(0x5efb75ea, 0x55cde31e), + WTCP(0x5eb37285, 0x561d5771), WTCP(0x5e6b2ca8, 0x566c8f55), WTCP(0x5e22a487, 0x56bb8a90), + WTCP(0x5dd9da55, 0x570a48ec), WTCP(0x5d90ce45, 0x5758ca31), WTCP(0x5d47808a, 0x57a70e29), + WTCP(0x5cfdf157, 0x57f5149d), WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5c6a0f59, 0x5890681a), + WTCP(0x5c1fbcf6, 0x58ddb4b8), WTCP(0x5bd529eb, 0x592ac2f7), WTCP(0x5b8a566c, 0x597792a1), + WTCP(0x5b3f42ae, 0x59c42381), WTCP(0x5af3eee6, 0x5a107561), WTCP(0x5aa85b48, 0x5a5c880a), +}; + +# ifdef ENABLE_HR_MODE +#ifdef CR8_G_ADD_75MS +const PWord32 SineWindow720[360] = { + WTCP(0x7ffffb01, 0x0023be8d), WTCP(0x7fffd314, 0x006b3b9b), WTCP(0x7fff833a, 0x00b2b888), + WTCP(0x7fff0b72, 0x00fa353e), WTCP(0x7ffe6bbe, 0x0141b1a5), WTCP(0x7ffda41c, 0x01892da8), + WTCP(0x7ffcb48e, 0x01d0a930), WTCP(0x7ffb9d14, 0x02182427), WTCP(0x7ffa5dae, 0x025f9e77), + WTCP(0x7ff8f65d, 0x02a7180a), WTCP(0x7ff76720, 0x02ee90c8), WTCP(0x7ff5aff9, 0x0336089d), + WTCP(0x7ff3d0e8, 0x037d7f71), WTCP(0x7ff1c9ee, 0x03c4f52e), WTCP(0x7fef9b0a, 0x040c69bf), + WTCP(0x7fed443f, 0x0453dd0c), WTCP(0x7feac58c, 0x049b4f00), WTCP(0x7fe81ef2, 0x04e2bf83), + WTCP(0x7fe55073, 0x052a2e81), WTCP(0x7fe25a0e, 0x05719be2), WTCP(0x7fdf3bc6, 0x05b90791), + WTCP(0x7fdbf59a, 0x06007176), WTCP(0x7fd8878d, 0x0647d97c), WTCP(0x7fd4f19f, 0x068f3f8d), + WTCP(0x7fd133d0, 0x06d6a392), WTCP(0x7fcd4e23, 0x071e0575), WTCP(0x7fc94099, 0x0765651f), + WTCP(0x7fc50b33, 0x07acc27b), WTCP(0x7fc0adf1, 0x07f41d72), WTCP(0x7fbc28d6, 0x083b75ee), + WTCP(0x7fb77be3, 0x0882cbd8), WTCP(0x7fb2a71a, 0x08ca1f1b), WTCP(0x7fadaa7b, 0x09116fa0), + WTCP(0x7fa88608, 0x0958bd51), WTCP(0x7fa339c4, 0x09a00817), WTCP(0x7f9dc5b0, 0x09e74fdd), + WTCP(0x7f9829cc, 0x0a2e948c), WTCP(0x7f92661c, 0x0a75d60e), WTCP(0x7f8c7aa1, 0x0abd144d), + WTCP(0x7f86675c, 0x0b044f32), WTCP(0x7f802c51, 0x0b4b86a8), WTCP(0x7f79c980, 0x0b92ba97), + WTCP(0x7f733eeb, 0x0bd9eaeb), WTCP(0x7f6c8c95, 0x0c21178c), WTCP(0x7f65b280, 0x0c684064), + WTCP(0x7f5eb0ae, 0x0caf655e), WTCP(0x7f578720, 0x0cf68662), WTCP(0x7f5035da, 0x0d3da35c), + WTCP(0x7f48bcde, 0x0d84bc34), WTCP(0x7f411c2e, 0x0dcbd0d5), WTCP(0x7f3953cb, 0x0e12e128), + WTCP(0x7f3163ba, 0x0e59ed17), WTCP(0x7f294bfc, 0x0ea0f48c), WTCP(0x7f210c93, 0x0ee7f771), + WTCP(0x7f18a583, 0x0f2ef5b0), WTCP(0x7f1016cd, 0x0f75ef32), WTCP(0x7f076075, 0x0fbce3e2), + WTCP(0x7efe827e, 0x1003d3a9), WTCP(0x7ef57cea, 0x104abe71), WTCP(0x7eec4fbb, 0x1091a424), + WTCP(0x7ee2faf5, 0x10d884ad), WTCP(0x7ed97e9b, 0x111f5ff3), WTCP(0x7ecfdaaf, 0x116635e3), + WTCP(0x7ec60f35, 0x11ad0665), WTCP(0x7ebc1c30, 0x11f3d164), WTCP(0x7eb201a2, 0x123a96c9), + WTCP(0x7ea7bf90, 0x1281567f), WTCP(0x7e9d55fb, 0x12c8106e), WTCP(0x7e92c4e8, 0x130ec482), + WTCP(0x7e880c5a, 0x135572a5), WTCP(0x7e7d2c53, 0x139c1abf), WTCP(0x7e7224d8, 0x13e2bcbb), + WTCP(0x7e66f5ec, 0x14295884), WTCP(0x7e5b9f92, 0x146fee02), WTCP(0x7e5021ce, 0x14b67d21), + WTCP(0x7e447ca3, 0x14fd05c9), WTCP(0x7e38b016, 0x154387e6), WTCP(0x7e2cbc29, 0x158a0360), + WTCP(0x7e20a0e1, 0x15d07823), WTCP(0x7e145e41, 0x1616e618), WTCP(0x7e07f44d, 0x165d4d28), + WTCP(0x7dfb6309, 0x16a3ad3f), WTCP(0x7deeaa79, 0x16ea0646), WTCP(0x7de1caa1, 0x17305827), + WTCP(0x7dd4c384, 0x1776a2cd), WTCP(0x7dc79528, 0x17bce621), WTCP(0x7dba3f90, 0x1803220d), + WTCP(0x7dacc2c0, 0x1849567c), WTCP(0x7d9f1ebc, 0x188f8357), WTCP(0x7d915389, 0x18d5a889), + WTCP(0x7d83612b, 0x191bc5fc), WTCP(0x7d7547a6, 0x1961db9b), WTCP(0x7d6706ff, 0x19a7e94e), + WTCP(0x7d589f3a, 0x19edef00), WTCP(0x7d4a105c, 0x1a33ec9c), WTCP(0x7d3b5a69, 0x1a79e20c), + WTCP(0x7d2c7d66, 0x1abfcf39), WTCP(0x7d1d7957, 0x1b05b40e), WTCP(0x7d0e4e41, 0x1b4b9076), + WTCP(0x7cfefc29, 0x1b91645a), WTCP(0x7cef8314, 0x1bd72fa4), WTCP(0x7cdfe306, 0x1c1cf23f), + WTCP(0x7cd01c05, 0x1c62ac16), WTCP(0x7cc02e14, 0x1ca85d12), WTCP(0x7cb0193a, 0x1cee051d), + WTCP(0x7c9fdd7b, 0x1d33a422), WTCP(0x7c8f7add, 0x1d793a0b), WTCP(0x7c7ef164, 0x1dbec6c3), + WTCP(0x7c6e4115, 0x1e044a33), WTCP(0x7c5d69f6, 0x1e49c447), WTCP(0x7c4c6c0d, 0x1e8f34e8), + WTCP(0x7c3b475d, 0x1ed49c00), WTCP(0x7c29fbed, 0x1f19f97b), WTCP(0x7c1889c3, 0x1f5f4d42), + WTCP(0x7c06f0e2, 0x1fa49740), WTCP(0x7bf53152, 0x1fe9d75f), WTCP(0x7be34b17, 0x202f0d8a), + WTCP(0x7bd13e38, 0x207439aa), WTCP(0x7bbf0ab9, 0x20b95bac), WTCP(0x7bacb0a0, 0x20fe7378), + WTCP(0x7b9a2ff4, 0x214380f9), WTCP(0x7b8788b9, 0x2188841a), WTCP(0x7b74baf7, 0x21cd7cc5), + WTCP(0x7b61c6b2, 0x22126ae5), WTCP(0x7b4eabf0, 0x22574e65), WTCP(0x7b3b6ab8, 0x229c272e), + WTCP(0x7b28030f, 0x22e0f52b), WTCP(0x7b1474fc, 0x2325b847), WTCP(0x7b00c085, 0x236a706d), + WTCP(0x7aece5af, 0x23af1d86), WTCP(0x7ad8e481, 0x23f3bf7e), WTCP(0x7ac4bd02, 0x2438563f), + WTCP(0x7ab06f36, 0x247ce1b4), WTCP(0x7a9bfb26, 0x24c161c7), WTCP(0x7a8760d7, 0x2505d663), + WTCP(0x7a72a050, 0x254a3f72), WTCP(0x7a5db997, 0x258e9ce0), WTCP(0x7a48acb2, 0x25d2ee97), + WTCP(0x7a3379a8, 0x26173481), WTCP(0x7a1e2081, 0x265b6e8a), WTCP(0x7a08a141, 0x269f9c9c), + WTCP(0x79f2fbf1, 0x26e3bea1), WTCP(0x79dd3097, 0x2727d485), WTCP(0x79c73f3a, 0x276bde33), + WTCP(0x79b127e0, 0x27afdb94), WTCP(0x799aea91, 0x27f3cc94), WTCP(0x79848753, 0x2837b11e), + WTCP(0x796dfe2d, 0x287b891c), WTCP(0x79574f27, 0x28bf547a), WTCP(0x79407a47, 0x29031322), + WTCP(0x79297f95, 0x2946c4ff), WTCP(0x79125f18, 0x298a69fc), WTCP(0x78fb18d6, 0x29ce0204), + WTCP(0x78e3acd8, 0x2a118d01), WTCP(0x78cc1b25, 0x2a550adf), WTCP(0x78b463c3, 0x2a987b89), + WTCP(0x789c86bb, 0x2adbdee9), WTCP(0x78848413, 0x2b1f34eb), WTCP(0x786c5bd4, 0x2b627d79), + WTCP(0x78540e04, 0x2ba5b87f), WTCP(0x783b9aac, 0x2be8e5e8), WTCP(0x782301d2, 0x2c2c059e), + WTCP(0x780a4380, 0x2c6f178d), WTCP(0x77f15fbb, 0x2cb21ba0), WTCP(0x77d8568d, 0x2cf511c2), + WTCP(0x77bf27fd, 0x2d37f9dd), WTCP(0x77a5d413, 0x2d7ad3de), WTCP(0x778c5ad6, 0x2dbd9faf), + WTCP(0x7772bc4f, 0x2e005d3c), WTCP(0x7758f885, 0x2e430c6f), WTCP(0x773f0f81, 0x2e85ad34), + WTCP(0x7725014b, 0x2ec83f76), WTCP(0x770acdeb, 0x2f0ac320), WTCP(0x76f07569, 0x2f4d381e), + WTCP(0x76d5f7cd, 0x2f8f9e5a), WTCP(0x76bb5520, 0x2fd1f5c1), WTCP(0x76a08d6a, 0x30143e3d), + WTCP(0x7685a0b2, 0x305677ba), WTCP(0x766a8f03, 0x3098a222), WTCP(0x764f5863, 0x30dabd63), + WTCP(0x7633fcdc, 0x311cc966), WTCP(0x76187c76, 0x315ec617), WTCP(0x75fcd739, 0x31a0b362), + WTCP(0x75e10d2f, 0x31e29131), WTCP(0x75c51e60, 0x32245f72), WTCP(0x75a90ad4, 0x32661e0e), + WTCP(0x758cd295, 0x32a7ccf2), WTCP(0x757075ab, 0x32e96c09), WTCP(0x7553f41f, 0x332afb3e), + WTCP(0x75374dfa, 0x336c7a7d), WTCP(0x751a8345, 0x33ade9b2), WTCP(0x74fd9409, 0x33ef48c8), + WTCP(0x74e0804f, 0x343097ab), WTCP(0x74c3481f, 0x3471d647), WTCP(0x74a5eb84, 0x34b30487), + WTCP(0x74886a86, 0x34f42256), WTCP(0x746ac52e, 0x35352fa1), WTCP(0x744cfb86, 0x35762c53), + WTCP(0x742f0d97, 0x35b71858), WTCP(0x7410fb6a, 0x35f7f39b), WTCP(0x73f2c509, 0x3638be09), + WTCP(0x73d46a7d, 0x3679778d), WTCP(0x73b5ebd0, 0x36ba2013), WTCP(0x7397490b, 0x36fab787), + WTCP(0x73788237, 0x373b3dd5), WTCP(0x7359975f, 0x377bb2e8), WTCP(0x733a888b, 0x37bc16ad), + WTCP(0x731b55c6, 0x37fc690f), WTCP(0x72fbff1a, 0x383ca9fb), WTCP(0x72dc848f, 0x387cd95b), + WTCP(0x72bce631, 0x38bcf71d), WTCP(0x729d2408, 0x38fd032d), WTCP(0x727d3e1f, 0x393cfd75), + WTCP(0x725d347f, 0x397ce5e3), WTCP(0x723d0733, 0x39bcbc62), WTCP(0x721cb645, 0x39fc80df), + WTCP(0x71fc41be, 0x3a3c3345), WTCP(0x71dba9aa, 0x3a7bd381), WTCP(0x71baee11, 0x3abb617f), + WTCP(0x719a0eff, 0x3afadd2b), WTCP(0x71790c7d, 0x3b3a4671), WTCP(0x7157e696, 0x3b799d3e), + WTCP(0x71369d54, 0x3bb8e17d), WTCP(0x711530c1, 0x3bf8131b), WTCP(0x70f3a0e8, 0x3c373205), + WTCP(0x70d1edd4, 0x3c763e26), WTCP(0x70b0178f, 0x3cb5376b), WTCP(0x708e1e23, 0x3cf41dc0), + WTCP(0x706c019b, 0x3d32f112), WTCP(0x7049c202, 0x3d71b14d), WTCP(0x70275f63, 0x3db05e5d), + WTCP(0x7004d9c7, 0x3deef830), WTCP(0x6fe2313b, 0x3e2d7eb0), WTCP(0x6fbf65c8, 0x3e6bf1cc), + WTCP(0x6f9c7779, 0x3eaa516f), WTCP(0x6f79665a, 0x3ee89d86), WTCP(0x6f563276, 0x3f26d5fd), + WTCP(0x6f32dbd7, 0x3f64fac2), WTCP(0x6f0f6288, 0x3fa30bc0), WTCP(0x6eebc694, 0x3fe108e5), + WTCP(0x6ec80808, 0x401ef21d), WTCP(0x6ea426ed, 0x405cc754), WTCP(0x6e80234e, 0x409a8878), + WTCP(0x6e5bfd38, 0x40d83575), WTCP(0x6e37b4b6, 0x4115ce38), WTCP(0x6e1349d2, 0x415352ad), + WTCP(0x6deebc98, 0x4190c2c3), WTCP(0x6dca0d14, 0x41ce1e64), WTCP(0x6da53b50, 0x420b657f), + WTCP(0x6d804759, 0x42489800), WTCP(0x6d5b313a, 0x4285b5d4), WTCP(0x6d35f8ff, 0x42c2bee7), + WTCP(0x6d109eb2, 0x42ffb328), WTCP(0x6ceb2260, 0x433c9283), WTCP(0x6cc58415, 0x43795ce4), + WTCP(0x6c9fc3dc, 0x43b6123a), WTCP(0x6c79e1c1, 0x43f2b270), WTCP(0x6c53ddd0, 0x442f3d75), + WTCP(0x6c2db815, 0x446bb335), WTCP(0x6c07709b, 0x44a8139d), WTCP(0x6be1076e, 0x44e45e9b), + WTCP(0x6bba7c9b, 0x4520941b), WTCP(0x6b93d02d, 0x455cb40c), WTCP(0x6b6d0232, 0x4598be59), + WTCP(0x6b4612b3, 0x45d4b2f1), WTCP(0x6b1f01bf, 0x461091c1), WTCP(0x6af7cf60, 0x464c5ab6), + WTCP(0x6ad07ba4, 0x46880dbd), WTCP(0x6aa90696, 0x46c3aac5), WTCP(0x6a817043, 0x46ff31b9), + WTCP(0x6a59b8b7, 0x473aa288), WTCP(0x6a31dfff, 0x4775fd1f), WTCP(0x6a09e626, 0x47b1416c), + WTCP(0x69e1cb3a, 0x47ec6f5b), WTCP(0x69b98f47, 0x482786dc), WTCP(0x6991325a, 0x486287da), + WTCP(0x6968b47e, 0x489d7245), WTCP(0x694015c2, 0x48d84609), WTCP(0x69175630, 0x49130314), + WTCP(0x68ee75d7, 0x494da953), WTCP(0x68c574c3, 0x498838b6), WTCP(0x689c5300, 0x49c2b128), + WTCP(0x6873109c, 0x49fd1298), WTCP(0x6849ada3, 0x4a375cf4), WTCP(0x68202a22, 0x4a71902a), + WTCP(0x67f68626, 0x4aabac27), WTCP(0x67ccc1bd, 0x4ae5b0d9), WTCP(0x67a2dcf3, 0x4b1f9e2f), + WTCP(0x6778d7d5, 0x4b597416), WTCP(0x674eb270, 0x4b93327b), WTCP(0x67246cd3, 0x4bccd94e), + WTCP(0x66fa0708, 0x4c06687c), WTCP(0x66cf811f, 0x4c3fdff3), WTCP(0x66a4db24, 0x4c793fa1), + WTCP(0x667a1524, 0x4cb28775), WTCP(0x664f2f2e, 0x4cebb75c), WTCP(0x6624294d, 0x4d24cf44), + WTCP(0x65f90390, 0x4d5dcf1c), WTCP(0x65cdbe05, 0x4d96b6d3), WTCP(0x65a258b7, 0x4dcf8655), + WTCP(0x6576d3b6, 0x4e083d93), WTCP(0x654b2f0f, 0x4e40dc78), WTCP(0x651f6acf, 0x4e7962f6), + WTCP(0x64f38704, 0x4eb1d0f8), WTCP(0x64c783bc, 0x4eea266f), WTCP(0x649b6104, 0x4f226348), + WTCP(0x646f1eeb, 0x4f5a8772), WTCP(0x6442bd7d, 0x4f9292db), WTCP(0x64163cc9, 0x4fca8572), + WTCP(0x63e99cdd, 0x50025f26), WTCP(0x63bcddc6, 0x503a1fe4), WTCP(0x638fff93, 0x5071c79c), + WTCP(0x63630252, 0x50a9563d), WTCP(0x6335e610, 0x50e0cbb4), WTCP(0x6308aadc, 0x511827f0), + WTCP(0x62db50c4, 0x514f6ae1), WTCP(0x62add7d5, 0x51869476), WTCP(0x6280401f, 0x51bda49c), + WTCP(0x625289af, 0x51f49b42), WTCP(0x6224b494, 0x522b7859), WTCP(0x61f6c0dc, 0x52623bcd), + WTCP(0x61c8ae94, 0x5298e58f), WTCP(0x619a7dcd, 0x52cf758e), WTCP(0x616c2e93, 0x5305ebb8), + WTCP(0x613dc0f6, 0x533c47fc), WTCP(0x610f3504, 0x53728a49), WTCP(0x60e08acb, 0x53a8b28f), + WTCP(0x60b1c25b, 0x53dec0bc), WTCP(0x6082dbc0, 0x5414b4c0), WTCP(0x6053d70c, 0x544a8e8a), + WTCP(0x6024b44b, 0x54804e09), WTCP(0x5ff5738c, 0x54b5f32c), WTCP(0x5fc614df, 0x54eb7de2), + WTCP(0x5f969852, 0x5520ee1c), WTCP(0x5f66fdf4, 0x555643c8), WTCP(0x5f3745d4, 0x558b7ed5), + WTCP(0x5f077001, 0x55c09f33), WTCP(0x5ed77c89, 0x55f5a4d2), WTCP(0x5ea76b7c, 0x562a8fa0), + WTCP(0x5e773ce8, 0x565f5f8e), WTCP(0x5e46f0dc, 0x5694148a), WTCP(0x5e168769, 0x56c8ae85), + WTCP(0x5de6009c, 0x56fd2d6e), WTCP(0x5db55c85, 0x57319134), WTCP(0x5d849b33, 0x5765d9c8), + WTCP(0x5d53bcb5, 0x579a0719), WTCP(0x5d22c11b, 0x57ce1916), WTCP(0x5cf1a874, 0x58020fb0), + WTCP(0x5cc072ce, 0x5835ead6), WTCP(0x5c8f203a, 0x5869aa78), WTCP(0x5c5db0c7, 0x589d4e87), + WTCP(0x5c2c2484, 0x58d0d6f0), WTCP(0x5bfa7b81, 0x590443a6), WTCP(0x5bc8b5cd, 0x59379497), + WTCP(0x5b96d378, 0x596ac9b5), WTCP(0x5b64d491, 0x599de2ed), WTCP(0x5b32b928, 0x59d0e032), + WTCP(0x5b00814c, 0x5a03c172), WTCP(0x5ace2d0e, 0x5a36869f), WTCP(0x5a9bbc7c, 0x5a692fa7) +}; +#endif + +const PWord32 SineWindow960[480] = { + WTCP(0x7ffffd30, 0x001aceea), WTCP(0x7fffe6bb, 0x00506cb9), WTCP(0x7fffb9d0, 0x00860a79), + WTCP(0x7fff7670, 0x00bba822), WTCP(0x7fff1c9a, 0x00f145ab), WTCP(0x7ffeac4f, 0x0126e309), + WTCP(0x7ffe258f, 0x015c8033), WTCP(0x7ffd8859, 0x01921d20), WTCP(0x7ffcd4af, 0x01c7b9c6), + WTCP(0x7ffc0a90, 0x01fd561d), WTCP(0x7ffb29fc, 0x0232f21a), WTCP(0x7ffa32f3, 0x02688db4), + WTCP(0x7ff92576, 0x029e28e2), WTCP(0x7ff80185, 0x02d3c39b), WTCP(0x7ff6c71f, 0x03095dd5), + WTCP(0x7ff57646, 0x033ef786), WTCP(0x7ff40ef9, 0x037490a5), WTCP(0x7ff29139, 0x03aa292a), + WTCP(0x7ff0fd06, 0x03dfc109), WTCP(0x7fef525f, 0x0415583b), WTCP(0x7fed9147, 0x044aeeb5), + WTCP(0x7febb9bc, 0x0480846e), WTCP(0x7fe9cbbf, 0x04b6195d), WTCP(0x7fe7c751, 0x04ebad79), + WTCP(0x7fe5ac71, 0x052140b7), WTCP(0x7fe37b21, 0x0556d30f), WTCP(0x7fe13360, 0x058c6478), + WTCP(0x7fded52f, 0x05c1f4e7), WTCP(0x7fdc608e, 0x05f78453), WTCP(0x7fd9d57e, 0x062d12b3), + WTCP(0x7fd73400, 0x06629ffe), WTCP(0x7fd47c13, 0x06982c2b), WTCP(0x7fd1adb8, 0x06cdb72f), + WTCP(0x7fcec8f0, 0x07034101), WTCP(0x7fcbcdbb, 0x0738c998), WTCP(0x7fc8bc1a, 0x076e50eb), + WTCP(0x7fc5940d, 0x07a3d6f0), WTCP(0x7fc25595, 0x07d95b9e), WTCP(0x7fbf00b2, 0x080edeec), + WTCP(0x7fbb9566, 0x084460cf), WTCP(0x7fb813af, 0x0879e140), WTCP(0x7fb47b90, 0x08af6033), + WTCP(0x7fb0cd09, 0x08e4dda0), WTCP(0x7fad081a, 0x091a597e), WTCP(0x7fa92cc4, 0x094fd3c3), + WTCP(0x7fa53b08, 0x09854c66), WTCP(0x7fa132e7, 0x09bac35d), WTCP(0x7f9d1460, 0x09f0389f), + WTCP(0x7f98df76, 0x0a25ac22), WTCP(0x7f949428, 0x0a5b1dde), WTCP(0x7f903278, 0x0a908dc9), + WTCP(0x7f8bba65, 0x0ac5fbd9), WTCP(0x7f872bf2, 0x0afb6805), WTCP(0x7f82871e, 0x0b30d244), + WTCP(0x7f7dcbeb, 0x0b663a8c), WTCP(0x7f78fa5a, 0x0b9ba0d5), WTCP(0x7f74126a, 0x0bd10513), + WTCP(0x7f6f141e, 0x0c06673f), WTCP(0x7f69ff75, 0x0c3bc74f), WTCP(0x7f64d472, 0x0c71253a), + WTCP(0x7f5f9314, 0x0ca680f5), WTCP(0x7f5a3b5d, 0x0cdbda79), WTCP(0x7f54cd4e, 0x0d1131ba), + WTCP(0x7f4f48e7, 0x0d4686b1), WTCP(0x7f49ae29, 0x0d7bd954), WTCP(0x7f43fd17, 0x0db12998), + WTCP(0x7f3e35af, 0x0de67776), WTCP(0x7f3857f5, 0x0e1bc2e4), WTCP(0x7f3263e8, 0x0e510bd7), + WTCP(0x7f2c5989, 0x0e865248), WTCP(0x7f2638da, 0x0ebb962c), WTCP(0x7f2001dc, 0x0ef0d77b), + WTCP(0x7f19b490, 0x0f26162a), WTCP(0x7f1350f7, 0x0f5b5231), WTCP(0x7f0cd711, 0x0f908b86), + WTCP(0x7f0646e1, 0x0fc5c220), WTCP(0x7effa068, 0x0ffaf5f6), WTCP(0x7ef8e3a5, 0x103026fe), + WTCP(0x7ef2109c, 0x1065552e), WTCP(0x7eeb274c, 0x109a807e), WTCP(0x7ee427b8, 0x10cfa8e5), + WTCP(0x7edd11e0, 0x1104ce58), WTCP(0x7ed5e5c5, 0x1139f0cf), WTCP(0x7ecea36a, 0x116f1040), + WTCP(0x7ec74ace, 0x11a42ca2), WTCP(0x7ebfdbf4, 0x11d945eb), WTCP(0x7eb856dd, 0x120e5c13), + WTCP(0x7eb0bb89, 0x12436f10), WTCP(0x7ea909fb, 0x12787ed8), WTCP(0x7ea14234, 0x12ad8b63), + WTCP(0x7e996435, 0x12e294a7), WTCP(0x7e916fff, 0x13179a9a), WTCP(0x7e896594, 0x134c9d34), + WTCP(0x7e8144f5, 0x13819c6b), WTCP(0x7e790e24, 0x13b69836), WTCP(0x7e70c123, 0x13eb908c), + WTCP(0x7e685df1, 0x14208562), WTCP(0x7e5fe492, 0x145576b1), WTCP(0x7e575507, 0x148a646e), + WTCP(0x7e4eaf50, 0x14bf4e91), WTCP(0x7e45f370, 0x14f43510), WTCP(0x7e3d2168, 0x152917e1), + WTCP(0x7e34393a, 0x155df6fc), WTCP(0x7e2b3ae7, 0x1592d257), WTCP(0x7e222671, 0x15c7a9ea), + WTCP(0x7e18fbd9, 0x15fc7da9), WTCP(0x7e0fbb21, 0x16314d8e), WTCP(0x7e06644b, 0x1666198d), + WTCP(0x7dfcf758, 0x169ae19f), WTCP(0x7df3744a, 0x16cfa5b9), WTCP(0x7de9db22, 0x170465d2), + WTCP(0x7de02be3, 0x173921e2), WTCP(0x7dd6668e, 0x176dd9de), WTCP(0x7dcc8b24, 0x17a28dbe), + WTCP(0x7dc299a8, 0x17d73d79), WTCP(0x7db8921b, 0x180be904), WTCP(0x7dae747f, 0x18409058), + WTCP(0x7da440d5, 0x1875336a), WTCP(0x7d99f720, 0x18a9d231), WTCP(0x7d8f9761, 0x18de6ca5), + WTCP(0x7d85219b, 0x191302bb), WTCP(0x7d7a95ce, 0x1947946c), WTCP(0x7d6ff3fd, 0x197c21ac), + WTCP(0x7d653c2a, 0x19b0aa75), WTCP(0x7d5a6e56, 0x19e52ebb), WTCP(0x7d4f8a84, 0x1a19ae76), + WTCP(0x7d4490b5, 0x1a4e299c), WTCP(0x7d3980eb, 0x1a82a025), WTCP(0x7d2e5b29, 0x1ab71208), + WTCP(0x7d231f6f, 0x1aeb7f3a), WTCP(0x7d17cdc1, 0x1b1fe7b3), WTCP(0x7d0c6620, 0x1b544b6a), + WTCP(0x7d00e88e, 0x1b88aa55), WTCP(0x7cf5550d, 0x1bbd046c), WTCP(0x7ce9aba0, 0x1bf159a4), + WTCP(0x7cddec47, 0x1c25a9f5), WTCP(0x7cd21706, 0x1c59f557), WTCP(0x7cc62bde, 0x1c8e3bbe), + WTCP(0x7cba2ad2, 0x1cc27d23), WTCP(0x7cae13e3, 0x1cf6b97c), WTCP(0x7ca1e714, 0x1d2af0c0), + WTCP(0x7c95a466, 0x1d5f22e6), WTCP(0x7c894bdd, 0x1d934fe5), WTCP(0x7c7cdd7a, 0x1dc777b3), + WTCP(0x7c70593f, 0x1dfb9a48), WTCP(0x7c63bf2e, 0x1e2fb79a), WTCP(0x7c570f4a, 0x1e63cfa0), + WTCP(0x7c4a4995, 0x1e97e251), WTCP(0x7c3d6e12, 0x1ecbefa3), WTCP(0x7c307cc1, 0x1efff78f), + WTCP(0x7c2375a7, 0x1f33fa0a), WTCP(0x7c1658c4, 0x1f67f70b), WTCP(0x7c09261c, 0x1f9bee8a), + WTCP(0x7bfbddb0, 0x1fcfe07d), WTCP(0x7bee7f84, 0x2003ccdb), WTCP(0x7be10b98, 0x2037b39b), + WTCP(0x7bd381f0, 0x206b94b4), WTCP(0x7bc5e28f, 0x209f701c), WTCP(0x7bb82d75, 0x20d345cb), + WTCP(0x7baa62a7, 0x210715b8), WTCP(0x7b9c8225, 0x213adfda), WTCP(0x7b8e8bf4, 0x216ea426), + WTCP(0x7b808014, 0x21a26295), WTCP(0x7b725e89, 0x21d61b1d), WTCP(0x7b642755, 0x2209cdb6), + WTCP(0x7b55da7b, 0x223d7a55), WTCP(0x7b4777fd, 0x227120f3), WTCP(0x7b38ffdd, 0x22a4c185), + WTCP(0x7b2a721e, 0x22d85c03), WTCP(0x7b1bcec3, 0x230bf064), WTCP(0x7b0d15cf, 0x233f7e9f), + WTCP(0x7afe4743, 0x237306ab), WTCP(0x7aef6323, 0x23a6887e), WTCP(0x7ae06970, 0x23da0410), + WTCP(0x7ad15a2f, 0x240d7958), WTCP(0x7ac23560, 0x2440e84c), WTCP(0x7ab2fb08, 0x247450e4), + WTCP(0x7aa3ab28, 0x24a7b316), WTCP(0x7a9445c4, 0x24db0eda), WTCP(0x7a84cadd, 0x250e6427), + WTCP(0x7a753a78, 0x2541b2f3), WTCP(0x7a659495, 0x2574fb35), WTCP(0x7a55d939, 0x25a83ce5), + WTCP(0x7a460867, 0x25db77fa), WTCP(0x7a36221f, 0x260eac6a), WTCP(0x7a262667, 0x2641da2c), + WTCP(0x7a16153f, 0x26750139), WTCP(0x7a05eeac, 0x26a82185), WTCP(0x79f5b2b0, 0x26db3b0a), + WTCP(0x79e5614e, 0x270e4dbd), WTCP(0x79d4fa88, 0x27415996), WTCP(0x79c47e62, 0x27745e8b), + WTCP(0x79b3ecdf, 0x27a75c95), WTCP(0x79a34601, 0x27da53a9), WTCP(0x799289cb, 0x280d43bf), + WTCP(0x7981b841, 0x28402cce), WTCP(0x7970d164, 0x28730ecd), WTCP(0x795fd539, 0x28a5e9b3), + WTCP(0x794ec3c2, 0x28d8bd78), WTCP(0x793d9d02, 0x290b8a11), WTCP(0x792c60fd, 0x293e4f77), + WTCP(0x791b0fb4, 0x29710da1), WTCP(0x7909a92c, 0x29a3c485), WTCP(0x78f82d67, 0x29d6741a), + WTCP(0x78e69c68, 0x2a091c59), WTCP(0x78d4f633, 0x2a3bbd37), WTCP(0x78c33aca, 0x2a6e56ac), + WTCP(0x78b16a31, 0x2aa0e8af), WTCP(0x789f846a, 0x2ad37338), WTCP(0x788d897a, 0x2b05f63d), + WTCP(0x787b7963, 0x2b3871b5), WTCP(0x78695427, 0x2b6ae598), WTCP(0x785719cb, 0x2b9d51dd), + WTCP(0x7844ca52, 0x2bcfb67b), WTCP(0x783265bf, 0x2c021368), WTCP(0x781fec14, 0x2c34689e), + WTCP(0x780d5d56, 0x2c66b611), WTCP(0x77fab988, 0x2c98fbba), WTCP(0x77e800ac, 0x2ccb3990), + WTCP(0x77d532c6, 0x2cfd6f8a), WTCP(0x77c24fda, 0x2d2f9d9f), WTCP(0x77af57eb, 0x2d61c3c6), + WTCP(0x779c4afb, 0x2d93e1f7), WTCP(0x7789290f, 0x2dc5f829), WTCP(0x7775f229, 0x2df80653), + WTCP(0x7762a64e, 0x2e2a0c6b), WTCP(0x774f4580, 0x2e5c0a6b), WTCP(0x773bcfc3, 0x2e8e0047), + WTCP(0x7728451b, 0x2ebfedf9), WTCP(0x7714a58a, 0x2ef1d377), WTCP(0x7700f114, 0x2f23b0b8), + WTCP(0x76ed27bd, 0x2f5585b4), WTCP(0x76d94988, 0x2f875262), WTCP(0x76c55679, 0x2fb916b9), + WTCP(0x76b14e92, 0x2fead2b0), WTCP(0x769d31d9, 0x301c863f), WTCP(0x7689004f, 0x304e315d), + WTCP(0x7674b9f9, 0x307fd401), WTCP(0x76605eda, 0x30b16e22), WTCP(0x764beef7, 0x30e2ffb9), + WTCP(0x76376a51, 0x311488bb), WTCP(0x7622d0ee, 0x31460921), WTCP(0x760e22d0, 0x317780e2), + WTCP(0x75f95ffb, 0x31a8eff5), WTCP(0x75e48874, 0x31da5651), WTCP(0x75cf9c3c, 0x320bb3ee), + WTCP(0x75ba9b59, 0x323d08c3), WTCP(0x75a585ce, 0x326e54c7), WTCP(0x75905b9f, 0x329f97f2), + WTCP(0x757b1ccf, 0x32d0d23b), WTCP(0x7565c961, 0x3302039a), WTCP(0x7550615b, 0x33332c06), + WTCP(0x753ae4bf, 0x33644b76), WTCP(0x75255392, 0x339561e1), WTCP(0x750fadd6, 0x33c66f3f), + WTCP(0x74f9f390, 0x33f77388), WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74ce4176, 0x345960b6), + WTCP(0x74b849a9, 0x348a498b), WTCP(0x74a23d61, 0x34bb2927), WTCP(0x748c1ca3, 0x34ebff83), + WTCP(0x7475e771, 0x351ccc95), WTCP(0x745f9dd0, 0x354d9056), WTCP(0x74493fc4, 0x357e4abd), + WTCP(0x7432cd51, 0x35aefbc1), WTCP(0x741c467a, 0x35dfa35a), WTCP(0x7405ab44, 0x3610417e), + WTCP(0x73eefbb2, 0x3640d627), WTCP(0x73d837c9, 0x3671614a), WTCP(0x73c15f8c, 0x36a1e2e0), + WTCP(0x73aa7300, 0x36d25ae0), WTCP(0x73937229, 0x3702c942), WTCP(0x737c5d0a, 0x37332dfc), + WTCP(0x736533a8, 0x37638907), WTCP(0x734df606, 0x3793da5a), WTCP(0x7336a42a, 0x37c421ed), + WTCP(0x731f3e16, 0x37f45fb7), WTCP(0x7307c3cf, 0x382493b0), WTCP(0x72f03559, 0x3854bdce), + WTCP(0x72d892b9, 0x3884de0b), WTCP(0x72c0dbf2, 0x38b4f45d), WTCP(0x72a91108, 0x38e500bb), + WTCP(0x72913200, 0x3915031e), WTCP(0x72793edf, 0x3944fb7d), WTCP(0x726137a7, 0x3974e9d0), + WTCP(0x72491c5d, 0x39a4ce0e), WTCP(0x7230ed06, 0x39d4a82e), WTCP(0x7218a9a6, 0x3a047829), + WTCP(0x72005241, 0x3a343df6), WTCP(0x71e7e6db, 0x3a63f98d), WTCP(0x71cf6779, 0x3a93aae5), + WTCP(0x71b6d41f, 0x3ac351f5), WTCP(0x719e2cd1, 0x3af2eeb7), WTCP(0x71857194, 0x3b228120), + WTCP(0x716ca26b, 0x3b520929), WTCP(0x7153bf5c, 0x3b8186ca), WTCP(0x713ac86a, 0x3bb0f9f9), + WTCP(0x7121bd9b, 0x3be062b0), WTCP(0x71089ef1, 0x3c0fc0e5), WTCP(0x70ef6c73, 0x3c3f1490), + WTCP(0x70d62624, 0x3c6e5da9), WTCP(0x70bccc08, 0x3c9d9c28), WTCP(0x70a35e25, 0x3cccd004), + WTCP(0x7089dc7e, 0x3cfbf935), WTCP(0x70704718, 0x3d2b17b3), WTCP(0x70569df7, 0x3d5a2b75), + WTCP(0x703ce121, 0x3d893473), WTCP(0x70231099, 0x3db832a5), WTCP(0x70092c64, 0x3de72603), + WTCP(0x6fef3487, 0x3e160e85), WTCP(0x6fd52906, 0x3e44ec22), WTCP(0x6fbb09e6, 0x3e73bed1), + WTCP(0x6fa0d72b, 0x3ea2868c), WTCP(0x6f8690da, 0x3ed14349), WTCP(0x6f6c36f7, 0x3efff500), + WTCP(0x6f51c988, 0x3f2e9baa), WTCP(0x6f374890, 0x3f5d373e), WTCP(0x6f1cb415, 0x3f8bc7b3), + WTCP(0x6f020c1b, 0x3fba4d02), WTCP(0x6ee750a7, 0x3fe8c723), WTCP(0x6ecc81bd, 0x4017360d), + WTCP(0x6eb19f63, 0x404599b8), WTCP(0x6e96a99c, 0x4073f21d), WTCP(0x6e7ba06e, 0x40a23f32), + WTCP(0x6e6083dd, 0x40d080f0), WTCP(0x6e4553ef, 0x40feb74f), WTCP(0x6e2a10a7, 0x412ce246), + WTCP(0x6e0eba0b, 0x415b01ce), WTCP(0x6df3501f, 0x418915de), WTCP(0x6dd7d2e9, 0x41b71e6e), + WTCP(0x6dbc426d, 0x41e51b77), WTCP(0x6da09eb0, 0x42130cf0), WTCP(0x6d84e7b6, 0x4240f2d1), + WTCP(0x6d691d86, 0x426ecd12), WTCP(0x6d4d4022, 0x429c9baa), WTCP(0x6d314f92, 0x42ca5e93), + WTCP(0x6d154bd8, 0x42f815c4), WTCP(0x6cf934fb, 0x4325c135), WTCP(0x6cdd0aff, 0x435360de), + WTCP(0x6cc0cde9, 0x4380f4b6), WTCP(0x6ca47dbe, 0x43ae7cb6), WTCP(0x6c881a83, 0x43dbf8d7), + WTCP(0x6c6ba43d, 0x4409690f), WTCP(0x6c4f1af2, 0x4436cd57), WTCP(0x6c327ea5, 0x446425a7), + WTCP(0x6c15cf5c, 0x449171f7), WTCP(0x6bf90d1c, 0x44beb240), WTCP(0x6bdc37eb, 0x44ebe678), + WTCP(0x6bbf4fcc, 0x45190e99), WTCP(0x6ba254c6, 0x45462a9a), WTCP(0x6b8546dd, 0x45733a73), + WTCP(0x6b682617, 0x45a03e1d), WTCP(0x6b4af278, 0x45cd358f), WTCP(0x6b2dac05, 0x45fa20c2), + WTCP(0x6b1052c5, 0x4626ffae), WTCP(0x6af2e6bb, 0x4653d24a), WTCP(0x6ad567ee, 0x46809890), + WTCP(0x6ab7d662, 0x46ad5277), WTCP(0x6a9a321c, 0x46d9fff7), WTCP(0x6a7c7b22, 0x4706a109), + WTCP(0x6a5eb179, 0x473335a5), WTCP(0x6a40d526, 0x475fbdc2), WTCP(0x6a22e62f, 0x478c3959), + WTCP(0x6a04e498, 0x47b8a863), WTCP(0x69e6d067, 0x47e50ad7), WTCP(0x69c8a9a1, 0x481160ae), + WTCP(0x69aa704b, 0x483da9e0), WTCP(0x698c246b, 0x4869e664), WTCP(0x696dc606, 0x48961634), + WTCP(0x694f5522, 0x48c23948), WTCP(0x6930d1c3, 0x48ee4f98), WTCP(0x69123bf0, 0x491a591b), + WTCP(0x68f393ad, 0x494655cb), WTCP(0x68d4d8ff, 0x497245a0), WTCP(0x68b60bed, 0x499e2892), + WTCP(0x68972c7c, 0x49c9fe99), WTCP(0x68783ab1, 0x49f5c7ad), WTCP(0x68593691, 0x4a2183c7), + WTCP(0x683a2022, 0x4a4d32e0), WTCP(0x681af769, 0x4a78d4ef), WTCP(0x67fbbc6c, 0x4aa469ed), + WTCP(0x67dc6f31, 0x4acff1d2), WTCP(0x67bd0fbc, 0x4afb6c97), WTCP(0x679d9e13, 0x4b26da34), + WTCP(0x677e1a3d, 0x4b523aa1), WTCP(0x675e843e, 0x4b7d8dd7), WTCP(0x673edc1b, 0x4ba8d3cf), + WTCP(0x671f21db, 0x4bd40c7f), WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x66df7719, 0x4c2a55ef), + WTCP(0x66bf86a2, 0x4c55669f), WTCP(0x669f8424, 0x4c8069ea), WTCP(0x667f6fa4, 0x4cab5fc9), + WTCP(0x665f4928, 0x4cd64834), WTCP(0x663f10b6, 0x4d012324), WTCP(0x661ec653, 0x4d2bf090), + WTCP(0x65fe6a05, 0x4d56b073), WTCP(0x65ddfbd2, 0x4d8162c3), WTCP(0x65bd7bc0, 0x4dac077b), + WTCP(0x659ce9d3, 0x4dd69e91), WTCP(0x657c4612, 0x4e0127ff), WTCP(0x655b9083, 0x4e2ba3be), + WTCP(0x653ac92a, 0x4e5611c5), WTCP(0x6519f00f, 0x4e80720d), WTCP(0x64f90537, 0x4eaac48f), + WTCP(0x64d808a7, 0x4ed50944), WTCP(0x64b6fa65, 0x4eff4024), WTCP(0x6495da78, 0x4f296927), + WTCP(0x6474a8e5, 0x4f538447), WTCP(0x645365b1, 0x4f7d917c), WTCP(0x643210e3, 0x4fa790be), + WTCP(0x6410aa80, 0x4fd18206), WTCP(0x63ef328f, 0x4ffb654c), WTCP(0x63cda915, 0x50253a8b), + WTCP(0x63ac0e18, 0x504f01b9), WTCP(0x638a619e, 0x5078bad0), WTCP(0x6368a3ac, 0x50a265c8), + WTCP(0x6346d44a, 0x50cc029b), WTCP(0x6324f37c, 0x50f59140), WTCP(0x63030149, 0x511f11b1), + WTCP(0x62e0fdb7, 0x514883e6), WTCP(0x62bee8cb, 0x5171e7d8), WTCP(0x629cc28c, 0x519b3d80), + WTCP(0x627a8aff, 0x51c484d6), WTCP(0x6258422b, 0x51edbdd3), WTCP(0x6235e815, 0x5216e870), + WTCP(0x62137cc4, 0x524004a6), WTCP(0x61f1003e, 0x5269126e), WTCP(0x61ce7289, 0x529211c0), + WTCP(0x61abd3aa, 0x52bb0295), WTCP(0x618923a8, 0x52e3e4e5), WTCP(0x61666289, 0x530cb8ab), + WTCP(0x61439053, 0x53357dde), WTCP(0x6120ad0c, 0x535e3478), WTCP(0x60fdb8ba, 0x5386dc71), + WTCP(0x60dab364, 0x53af75c2), WTCP(0x60b79d0f, 0x53d80064), WTCP(0x609475c2, 0x54007c50), + WTCP(0x60713d83, 0x5428e97f), WTCP(0x604df458, 0x545147ea), WTCP(0x602a9a47, 0x54799789), + WTCP(0x60072f56, 0x54a1d856), WTCP(0x5fe3b38d, 0x54ca0a4a), WTCP(0x5fc026f0, 0x54f22d5d), + WTCP(0x5f9c8986, 0x551a4188), WTCP(0x5f78db55, 0x554246c5), WTCP(0x5f551c64, 0x556a3d0c), + WTCP(0x5f314cb9, 0x55922457), WTCP(0x5f0d6c5b, 0x55b9fc9d), WTCP(0x5ee97b4e, 0x55e1c5da), + WTCP(0x5ec5799b, 0x56098004), WTCP(0x5ea16746, 0x56312b16), WTCP(0x5e7d4457, 0x5658c709), + WTCP(0x5e5910d4, 0x568053d5), WTCP(0x5e34ccc3, 0x56a7d173), WTCP(0x5e10782a, 0x56cf3fdd), + WTCP(0x5dec1310, 0x56f69f0c), WTCP(0x5dc79d7b, 0x571deef9), WTCP(0x5da31772, 0x57452f9d), + WTCP(0x5d7e80fb, 0x576c60f0), WTCP(0x5d59da1d, 0x579382ed), WTCP(0x5d3522dd, 0x57ba958c), + WTCP(0x5d105b43, 0x57e198c6), WTCP(0x5ceb8355, 0x58088c96), WTCP(0x5cc69b18, 0x582f70f2), + WTCP(0x5ca1a295, 0x585645d6), WTCP(0x5c7c99d0, 0x587d0b3a), WTCP(0x5c5780d2, 0x58a3c117), + WTCP(0x5c3257a0, 0x58ca6767), WTCP(0x5c0d1e40, 0x58f0fe22), WTCP(0x5be7d4ba, 0x59178542), + WTCP(0x5bc27b13, 0x593dfcc1), WTCP(0x5b9d1153, 0x59646497), WTCP(0x5b779780, 0x598abcbe), + WTCP(0x5b520da0, 0x59b1052e), WTCP(0x5b2c73ba, 0x59d73de2), WTCP(0x5b06c9d6, 0x59fd66d3), + WTCP(0x5ae10ff8, 0x5a237ff9), WTCP(0x5abb4628, 0x5a49894f), WTCP(0x5a956c6d, 0x5a6f82cd), +}; +# endif + +// fs 48 32 24 16 8 +// ms +-------------------- +// 10.0 | 480 320 240 160 80 +// 7.5 | 360 240 180 120 60 +// 5.0 | 240 160 120 80 40 +// 2.5 | 120 80 60 40 20 + +void BASOP_getTables( +#ifdef ENABLE_HR_MODE + const PWord32 **twiddle, const PWord32 **sin, +#else + const PWord16 **twiddle, const PWord16 **sin, +#endif + Word16 *sin_step, Word16 length) +{ + SWITCH (length) + { + case 20: + *sin = SineTable320; + move16(); + *sin_step = 32; + move16(); + *twiddle = SineWindow20; + move16(); + BREAK; + case 40: + *sin = SineTable320; + move16(); + *sin_step = 16; + move16(); + *twiddle = SineWindow40; + move16(); + BREAK; + case 60: + *sin = SineTable480; + move16(); + *sin_step = 16; + move16(); + *twiddle = SineWindow60; + move16(); + BREAK; + case 80: + *sin = SineTable320; + move16(); + *sin_step = 8; + move16(); + *twiddle = SineWindow80; + move16(); + BREAK; + case 120: + *sin = SineTable480; + move16(); + *sin_step = 8; + move16(); + *twiddle = SineWindow120; + move16(); + BREAK; + case 160: + *sin = SineTable320; + move16(); + *sin_step = 4; + move16(); + *twiddle = SineWindow160; + move16(); + BREAK; + case 180: + *sin = SineTable360; + move16(); + *sin_step = 4; + move16(); + *twiddle = SineWindow180; + move16(); + BREAK; + case 240: + *sin = SineTable480; + move16(); + *sin_step = 4; + move16(); + *twiddle = SineWindow240; + move16(); + BREAK; + case 320: + *sin = SineTable320; + move16(); + *sin_step = 2; + move16(); + *twiddle = SineWindow320; + move16(); + BREAK; + case 360: + *sin = SineTable360; + move16(); + *sin_step = 2; + move16(); + *twiddle = SineWindow360; + move16(); + BREAK; + case 480: + *sin = SineTable480; + move16(); + *sin_step = 2; + move16(); + *twiddle = SineWindow480; + move16(); + BREAK; +#ifdef ENABLE_HR_MODE +# ifdef CR8_G_ADD_75MS + case 720: + *sin = SineTable720; + move16(); + *sin_step = 2; + move16(); + *twiddle = SineWindow720; + move16(); + break; +# endif + case 960: + *sin = SineTable960; + move16(); + *sin_step = 2; + move16(); + *twiddle = SineWindow960; + move16(); + break; +#endif + default: ASSERT(0); + } +} + +const Word32 RealFFT32_twid[10] = { + 0x7fffffff, 0x00000000, 0x7d8a5f40, 0x18f8b83c, 0x7641af3d, + 0x30fbc54d, 0x6a6d98a4, 0x471cece7, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT40_twid[12] = { + 0x7fffffff, 0x00000000, 0x7e6c9251, 0x14060b68, 0x79bc384d, 0x278dde6e, + 0x720c8075, 0x3a1c5c57, 0x678dde6e, 0x4b3c8c12, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT64_twid[18] = { + 0x7fffffff, 0x00000000, 0x7f62368f, 0x0c8bd35e, 0x7d8a5f40, 0x18f8b83c, 0x7a7d055b, 0x25280c5e, 0x7641af3d, + 0x30fbc54d, 0x70e2cbc6, 0x3c56ba70, 0x6a6d98a4, 0x471cece7, 0x62f201ac, 0x5133cc94, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT80_twid[22] = { + 0x7fffffff, 0x00000000, 0x7f9afcb9, 0x0a0af299, 0x7e6c9251, 0x14060b68, 0x7c769e18, 0x1de189a6, + 0x79bc384d, 0x278dde6e, 0x7641af3d, 0x30fbc54d, 0x720c8075, 0x3a1c5c57, 0x6d23501b, 0x42e13ba4, + 0x678dde6e, 0x4b3c8c12, 0x6154fb91, 0x53211d18, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT96_twid[26] = { + 0x7fffffff, 0x00000000, 0x7fb9d759, 0x085f2137, 0x7ee7aa4c, 0x10b5150f, 0x7d8a5f40, 0x18f8b83c, 0x7ba3751d, + 0x2120fb83, 0x793501a9, 0x2924edac, 0x7641af3d, 0x30fbc54d, 0x72ccb9db, 0x389cea72, 0x6ed9eba1, 0x40000000, + 0x6a6d98a4, 0x471cece7, 0x658c9a2d, 0x4debe4fe, 0x603c496c, 0x54657194, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT128_twid[34] = { + 0x7fffffff, 0x00000000, 0x7fd8878e, 0x0647d97c, 0x7f62368f, 0x0c8bd35e, 0x7e9d55fc, 0x12c8106f, 0x7d8a5f40, + 0x18f8b83c, 0x7c29fbee, 0x1f19f97b, 0x7a7d055b, 0x25280c5e, 0x78848414, 0x2b1f34eb, 0x7641af3d, 0x30fbc54d, + 0x73b5ebd1, 0x36ba2014, 0x70e2cbc6, 0x3c56ba70, 0x6dca0d14, 0x41ce1e65, 0x6a6d98a4, 0x471cece7, 0x66cf8120, + 0x4c3fdff4, 0x62f201ac, 0x5133cc94, 0x5ed77c8a, 0x55f5a4d2, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT192_twid[50] = { + 0x7fffffff, 0x00000000, 0x7fee74a2, 0x0430238f, 0x7fb9d759, 0x085f2137, 0x7f62368f, 0x0c8bd35e, 0x7ee7aa4c, + 0x10b5150f, 0x7e4a5426, 0x14d9c245, 0x7d8a5f40, 0x18f8b83c, 0x7ca80038, 0x1d10d5c2, 0x7ba3751d, 0x2120fb83, + 0x7a7d055b, 0x25280c5e, 0x793501a9, 0x2924edac, 0x77cbc3f2, 0x2d168792, 0x7641af3d, 0x30fbc54d, 0x74972f92, + 0x34d3957e, 0x72ccb9db, 0x389cea72, 0x70e2cbc6, 0x3c56ba70, 0x6ed9eba1, 0x40000000, 0x6cb2a837, 0x4397ba32, + 0x6a6d98a4, 0x471cece7, 0x680b5c33, 0x4a8ea111, 0x658c9a2d, 0x4debe4fe, 0x62f201ac, 0x5133cc94, 0x603c496c, + 0x54657194, 0x5d6c2f99, 0x577ff3da, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT256_twid[66] = { + 0x7fffffff, 0x00000000, 0x7ff62182, 0x03242abf, 0x7fd8878e, 0x0647d97c, 0x7fa736b4, 0x096a9049, 0x7f62368f, + 0x0c8bd35e, 0x7f0991c4, 0x0fab272b, 0x7e9d55fc, 0x12c8106f, 0x7e1d93ea, 0x15e21445, 0x7d8a5f40, 0x18f8b83c, + 0x7ce3ceb2, 0x1c0b826a, 0x7c29fbee, 0x1f19f97b, 0x7b5d039e, 0x2223a4c5, 0x7a7d055b, 0x25280c5e, 0x798a23b1, + 0x2826b928, 0x78848414, 0x2b1f34eb, 0x776c4edb, 0x2e110a62, 0x7641af3d, 0x30fbc54d, 0x7504d345, 0x33def287, + 0x73b5ebd1, 0x36ba2014, 0x72552c85, 0x398cdd32, 0x70e2cbc6, 0x3c56ba70, 0x6f5f02b2, 0x3f1749b8, 0x6dca0d14, + 0x41ce1e65, 0x6c242960, 0x447acd50, 0x6a6d98a4, 0x471cece7, 0x68a69e81, 0x49b41533, 0x66cf8120, 0x4c3fdff4, + 0x64e88926, 0x4ebfe8a5, 0x62f201ac, 0x5133cc94, 0x60ec3830, 0x539b2af0, 0x5ed77c8a, 0x55f5a4d2, 0x5cb420e0, + 0x5842dd54, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT384_twid[98] = { + 0x7fffffff, 0x00000000, 0x7ffb9d15, 0x02182427, 0x7fee74a2, 0x0430238f, 0x7fd8878e, 0x0647d97c, 0x7fb9d759, + 0x085f2137, 0x7f92661d, 0x0a75d60e, 0x7f62368f, 0x0c8bd35e, 0x7f294bfd, 0x0ea0f48c, 0x7ee7aa4c, 0x10b5150f, + 0x7e9d55fc, 0x12c8106f, 0x7e4a5426, 0x14d9c245, 0x7deeaa7a, 0x16ea0646, 0x7d8a5f40, 0x18f8b83c, 0x7d1d7958, + 0x1b05b40f, 0x7ca80038, 0x1d10d5c2, 0x7c29fbee, 0x1f19f97b, 0x7ba3751d, 0x2120fb83, 0x7b1474fd, 0x2325b847, + 0x7a7d055b, 0x25280c5e, 0x79dd3098, 0x2727d486, 0x793501a9, 0x2924edac, 0x78848414, 0x2b1f34eb, 0x77cbc3f2, + 0x2d168792, 0x770acdec, 0x2f0ac320, 0x7641af3d, 0x30fbc54d, 0x757075ac, 0x32e96c09, 0x74972f92, 0x34d3957e, + 0x73b5ebd1, 0x36ba2014, 0x72ccb9db, 0x389cea72, 0x71dba9ab, 0x3a7bd382, 0x70e2cbc6, 0x3c56ba70, 0x6fe2313c, + 0x3e2d7eb1, 0x6ed9eba1, 0x40000000, 0x6dca0d14, 0x41ce1e65, 0x6cb2a837, 0x4397ba32, 0x6b93d02e, 0x455cb40c, + 0x6a6d98a4, 0x471cece7, 0x694015c3, 0x48d84609, 0x680b5c33, 0x4a8ea111, 0x66cf8120, 0x4c3fdff4, 0x658c9a2d, + 0x4debe4fe, 0x6442bd7e, 0x4f9292dc, 0x62f201ac, 0x5133cc94, 0x619a7dce, 0x52cf758f, 0x603c496c, 0x54657194, + 0x5ed77c8a, 0x55f5a4d2, 0x5d6c2f99, 0x577ff3da, 0x5bfa7b82, 0x590443a7, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT512_twid[130] = { + 0x7fffffff, 0x00000000, 0x7ffd885a, 0x01921d20, 0x7ff62182, 0x03242abf, 0x7fe9cbc0, 0x04b6195d, 0x7fd8878e, + 0x0647d97c, 0x7fc25596, 0x07d95b9e, 0x7fa736b4, 0x096a9049, 0x7f872bf3, 0x0afb6805, 0x7f62368f, 0x0c8bd35e, + 0x7f3857f6, 0x0e1bc2e4, 0x7f0991c4, 0x0fab272b, 0x7ed5e5c6, 0x1139f0cf, 0x7e9d55fc, 0x12c8106f, 0x7e5fe493, + 0x145576b1, 0x7e1d93ea, 0x15e21445, 0x7dd6668f, 0x176dd9de, 0x7d8a5f40, 0x18f8b83c, 0x7d3980ec, 0x1a82a026, + 0x7ce3ceb2, 0x1c0b826a, 0x7c894bde, 0x1d934fe5, 0x7c29fbee, 0x1f19f97b, 0x7bc5e290, 0x209f701c, 0x7b5d039e, + 0x2223a4c5, 0x7aef6323, 0x23a6887f, 0x7a7d055b, 0x25280c5e, 0x7a05eead, 0x26a82186, 0x798a23b1, 0x2826b928, + 0x7909a92d, 0x29a3c485, 0x78848414, 0x2b1f34eb, 0x77fab989, 0x2c98fbba, 0x776c4edb, 0x2e110a62, 0x76d94989, + 0x2f875262, 0x7641af3d, 0x30fbc54d, 0x75a585cf, 0x326e54c7, 0x7504d345, 0x33def287, 0x745f9dd1, 0x354d9057, + 0x73b5ebd1, 0x36ba2014, 0x7307c3d0, 0x382493b0, 0x72552c85, 0x398cdd32, 0x719e2cd2, 0x3af2eeb7, 0x70e2cbc6, + 0x3c56ba70, 0x7023109a, 0x3db832a6, 0x6f5f02b2, 0x3f1749b8, 0x6e96a99d, 0x4073f21d, 0x6dca0d14, 0x41ce1e65, + 0x6cf934fc, 0x4325c135, 0x6c242960, 0x447acd50, 0x6b4af279, 0x45cd358f, 0x6a6d98a4, 0x471cece7, 0x698c246c, + 0x4869e665, 0x68a69e81, 0x49b41533, 0x67bd0fbd, 0x4afb6c98, 0x66cf8120, 0x4c3fdff4, 0x65ddfbd3, 0x4d8162c4, + 0x64e88926, 0x4ebfe8a5, 0x63ef3290, 0x4ffb654d, 0x62f201ac, 0x5133cc94, 0x61f1003f, 0x5269126e, 0x60ec3830, + 0x539b2af0, 0x5fe3b38d, 0x54ca0a4b, 0x5ed77c8a, 0x55f5a4d2, 0x5dc79d7c, 0x571deefa, 0x5cb420e0, 0x5842dd54, + 0x5b9d1154, 0x59646498, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RealFFT768_twid[194] = { + 0x7fffffff, 0x00000000, 0x7ffee744, 0x010c1460, 0x7ffb9d15, 0x02182427, 0x7ff62182, 0x03242abf, 0x7fee74a2, + 0x0430238f, 0x7fe49698, 0x053c0a01, 0x7fd8878e, 0x0647d97c, 0x7fca47b9, 0x07538d6b, 0x7fb9d759, 0x085f2137, + 0x7fa736b4, 0x096a9049, 0x7f92661d, 0x0a75d60e, 0x7f7b65ef, 0x0b80edf1, 0x7f62368f, 0x0c8bd35e, 0x7f46d86c, + 0x0d9681c2, 0x7f294bfd, 0x0ea0f48c, 0x7f0991c4, 0x0fab272b, 0x7ee7aa4c, 0x10b5150f, 0x7ec3962a, 0x11beb9aa, + 0x7e9d55fc, 0x12c8106f, 0x7e74ea6a, 0x13d114d0, 0x7e4a5426, 0x14d9c245, 0x7e1d93ea, 0x15e21445, 0x7deeaa7a, + 0x16ea0646, 0x7dbd98a4, 0x17f193c5, 0x7d8a5f40, 0x18f8b83c, 0x7d54ff2e, 0x19ff6f2a, 0x7d1d7958, 0x1b05b40f, + 0x7ce3ceb2, 0x1c0b826a, 0x7ca80038, 0x1d10d5c2, 0x7c6a0ef2, 0x1e15a99a, 0x7c29fbee, 0x1f19f97b, 0x7be7c847, + 0x201dc0ef, 0x7ba3751d, 0x2120fb83, 0x7b5d039e, 0x2223a4c5, 0x7b1474fd, 0x2325b847, 0x7ac9ca7a, 0x2427319d, + 0x7a7d055b, 0x25280c5e, 0x7a2e26f2, 0x26284422, 0x79dd3098, 0x2727d486, 0x798a23b1, 0x2826b928, 0x793501a9, + 0x2924edac, 0x78ddcbf5, 0x2a226db5, 0x78848414, 0x2b1f34eb, 0x78292b8d, 0x2c1b3efb, 0x77cbc3f2, 0x2d168792, + 0x776c4edb, 0x2e110a62, 0x770acdec, 0x2f0ac320, 0x76a742d1, 0x3003ad85, 0x7641af3d, 0x30fbc54d, 0x75da14ef, + 0x31f30638, 0x757075ac, 0x32e96c09, 0x7504d345, 0x33def287, 0x74972f92, 0x34d3957e, 0x74278c72, 0x35c750bc, + 0x73b5ebd1, 0x36ba2014, 0x73424fa0, 0x37abff5d, 0x72ccb9db, 0x389cea72, 0x72552c85, 0x398cdd32, 0x71dba9ab, + 0x3a7bd382, 0x71603361, 0x3b69c947, 0x70e2cbc6, 0x3c56ba70, 0x706374ff, 0x3d42a2ec, 0x6fe2313c, 0x3e2d7eb1, + 0x6f5f02b2, 0x3f1749b8, 0x6ed9eba1, 0x40000000, 0x6e52ee52, 0x40e79d8c, 0x6dca0d14, 0x41ce1e65, 0x6d3f4a40, + 0x42b37e96, 0x6cb2a837, 0x4397ba32, 0x6c242960, 0x447acd50, 0x6b93d02e, 0x455cb40c, 0x6b019f1a, 0x463d6a87, + 0x6a6d98a4, 0x471cece7, 0x69d7bf57, 0x47fb3757, 0x694015c3, 0x48d84609, 0x68a69e81, 0x49b41533, 0x680b5c33, + 0x4a8ea111, 0x676e5183, 0x4b67e5e4, 0x66cf8120, 0x4c3fdff4, 0x662eedc3, 0x4d168b8b, 0x658c9a2d, 0x4debe4fe, + 0x64e88926, 0x4ebfe8a5, 0x6442bd7e, 0x4f9292dc, 0x639b3a0b, 0x5063e008, 0x62f201ac, 0x5133cc94, 0x62471749, + 0x520254ef, 0x619a7dce, 0x52cf758f, 0x60ec3830, 0x539b2af0, 0x603c496c, 0x54657194, 0x5f8ab487, 0x552e4605, + 0x5ed77c8a, 0x55f5a4d2, 0x5e22a487, 0x56bb8a90, 0x5d6c2f99, 0x577ff3da, 0x5cb420e0, 0x5842dd54, 0x5bfa7b82, + 0x590443a7, 0x5b3f42ae, 0x59c42381, 0x5a82799a, 0x5a82799a, +}; + +const Word32 RotVector_32_32[2 * 20] = { + 0x7d8a5f00, 0xe70747c0, 0x7641b000, 0xcf043ac0, 0x6a6d9900, 0xb8e31300, 0x5a827980, 0xa57d8680, + 0x471ced80, 0x95926780, 0x30fbc600, 0x89be5100, 0x18f8b800, 0x8275a100, 0x7641b000, 0xcf043ac0, + 0x5a827980, 0xa57d8680, 0x30fbc600, 0x89be5100, 0xcf043b00, 0x89be5100, 0xa57d8680, 0xa57d8680, + 0x89be5100, 0xcf043ac0, 0x6a6d9900, 0xb8e31300, 0x30fbc600, 0x89be5100, 0xe7074800, 0x8275a100, + 0xa57d8680, 0xa57d8680, 0x8275a100, 0xe70747c0, 0x89be5000, 0x30fbc540, 0xb8e31280, 0x6a6d9880, +}; + +const Word32 RotVector_40_32[2 * 28] = { + 0x7e6c9251, 0x14060b68, 0x79bc384d, 0x278dde6e, 0x720c8075, 0x3a1c5c57, 0x678dde6e, 0x4b3c8c12, + 0x79bc384d, 0x278dde6e, 0x678dde6e, 0x4b3c8c12, 0x4b3c8c12, 0x678dde6e, 0x278dde6e, 0x79bc384d, + 0x720c8075, 0x3a1c5c57, 0x4b3c8c12, 0x678dde6e, 0x14060b68, 0x7e6c9251, 0xd8722192, 0x79bc384d, + 0x678dde6e, 0x4b3c8c12, 0x278dde6e, 0x79bc384d, 0xd8722192, 0x79bc384d, 0x98722192, 0x4b3c8c12, + 0x5a82799a, 0x5a82799a, 0x00000000, 0x7fffffff, 0xa57d8666, 0x5a82799a, 0x80000000, 0x00000000, + 0x4b3c8c12, 0x678dde6e, 0xd8722192, 0x79bc384d, 0x8643c7b3, 0x278dde6e, 0x98722192, 0xb4c373ee, + 0x3a1c5c57, 0x720c8075, 0xb4c373ee, 0x678dde6e, 0x81936daf, 0xebf9f498, 0xd8722192, 0x8643c7b3, +}; + +# ifdef ENABLE_HR_MODE +const Word32 RotVector_480[2 * (480 - 30)] = { +# else +const Word16 RotVector_480[2 * (480 - 30)] = { +# endif + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ff4c56f), SHC(0xfca63bd8), SHC(0x7fd317b4), SHC(0xf94d0e2e), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7ddb4bfc), SHC(0xe8ac819d), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7aba9ae6), SHC(0xdba5629b), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x78a879f4), SHC(0xd545d11c), SHC(0x777f903c), SHC(0xd220ffc0), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x7387ea23), SHC(0xc8e5032b), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x707d1443), SHC(0xc2ec7635), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x697cf78a), SHC(0xb780001c), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x637984d4), SHC(0xaf726def), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x5cd91140), SHC(0xa7e3ff4d), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6b598ea3), SHC(0xba4944a2), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x637984d4), SHC(0xaf726def), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x508d9211), SHC(0x9c867b2c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x45b6bb5e), SHC(0x94a6715d), SHC(0x40000000), SHC(0x9126145f), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x340ff242), SHC(0x8b10f144), SHC(0x2ddf0040), SHC(0x88806fc4), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x06b2f1d2), SHC(0x802ce84c), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7e6c9251), SHC(0xebf9f498), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x678dde6e), SHC(0xb4c373ee), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x53211d18), SHC(0x9eab046f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x3a1c5c57), SHC(0x8df37f8b), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1de189a6), SHC(0x838961e8), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0a0af299), SHC(0x80650347), SHC(0x00000000), SHC(0x80000000), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xebf9f498), SHC(0x81936daf), SHC(0xe21e765a), SHC(0x838961e8), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb4c373ee), SHC(0x98722192), SHC(0xacdee2e8), SHC(0x9eab046f), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x55a6125c), SHC(0xa0e0a15f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x40000000), SHC(0x9126145f), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0x00000000), SHC(0x80000000), SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe5632654), SHC(0x82cc0f36), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcbf00dbe), SHC(0x8b10f144), SHC(0xc0000000), SHC(0x9126145f), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0xa0e0a15f), SHC(0xaa59eda4), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x9126145f), SHC(0xc0000000), SHC(0x8b10f144), SHC(0xcbf00dbe), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x80b381ac), SHC(0xf29ecfb2), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x658c9a2d), SHC(0xb2141b02), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x40000000), SHC(0x9126145f), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x10b5150f), SHC(0x811855b4), + SHC(0x00000000), SHC(0x80000000), SHC(0xef4aeaf1), SHC(0x811855b4), SHC(0xdedf047d), SHC(0x845c8ae3), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc0000000), SHC(0x9126145f), SHC(0xb2141b02), SHC(0x9a7365d3), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9a7365d3), SHC(0xb2141b02), SHC(0x9126145f), SHC(0xc0000000), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x811855b4), SHC(0xef4aeaf1), + SHC(0x80000000), SHC(0x00000000), SHC(0x811855b4), SHC(0x10b5150f), SHC(0x845c8ae3), SHC(0x2120fb83), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9126145f), SHC(0x40000000), SHC(0x9a7365d3), SHC(0x4debe4fe), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x278dde6e), SHC(0x8643c7b3), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x00000000), SHC(0x80000000), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8df37f8b), SHC(0xc5e3a3a9), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x81936daf), SHC(0xebf9f498), SHC(0x80000000), SHC(0x00000000), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8df37f8b), SHC(0x3a1c5c57), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0xa57d8666), SHC(0x5a82799a), SHC(0xb4c373ee), SHC(0x678dde6e), + SHC(0xc5e3a3a9), SHC(0x720c8075), SHC(0xd8722192), SHC(0x79bc384d), SHC(0xebf9f498), SHC(0x7e6c9251), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ddb4bfc), SHC(0xe8ac819d), SHC(0x777f903c), SHC(0xd220ffc0), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x245a9d65), SHC(0x8545651a), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xc8e5032b), SHC(0x8c7815dd), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xa326eec0), SHC(0xa7e3ff4d), SHC(0x94a6715d), SHC(0xba4944a2), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x800b3a91), SHC(0xfca63bd8), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8757860c), SHC(0x2aba2ee4), SHC(0x9126145f), SHC(0x40000000), + SHC(0x9eab046f), SHC(0x53211d18), SHC(0xaf726def), SHC(0x637984d4), SHC(0xc2ec7635), SHC(0x707d1443), + SHC(0xd8722192), SHC(0x79bc384d), SHC(0xef4aeaf1), SHC(0x7ee7aa4c), SHC(0x06b2f1d2), SHC(0x7fd317b4), + SHC(0x1de189a6), SHC(0x7c769e18), SHC(0x340ff242), SHC(0x74ef0ebc), SHC(0x487fffe4), SHC(0x697cf78a), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffd3154), SHC(0xfe531484), SHC(0x7ff4c56f), SHC(0xfca63bd8), + SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7fb9d759), SHC(0xf7a0dec9), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f76892f), SHC(0xf449acca), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7eace58a), SHC(0xeda208a5), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7e26b371), SHC(0xea52c166), SHC(0x7ddb4bfc), SHC(0xe8ac819d), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7cd80464), SHC(0xe3c02fbb), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7c0fc22a), SHC(0xe07e0c84), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x7aba9ae6), SHC(0xdba5629b), SHC(0x7a3e17f2), SHC(0xda0aecf9), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x793501a9), SHC(0xd6db1254), SHC(0x78a879f4), SHC(0xd545d11c), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x76e33b3f), SHC(0xd09192ea), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7f9afcb9), SHC(0xf5f50d67), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x743e0918), SHC(0xca695b94), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x6d23501b), SHC(0xbd1ec45c), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x648543e4), SHC(0xb0c1878b), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5dfe47ad), SHC(0xa91d0ea3), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x53211d18), SHC(0x9eab046f), SHC(0x4f3e7875), SHC(0x9b7abc1c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x471cece7), SHC(0x9592675c), SHC(0x42e13ba4), SHC(0x92dcafe5), + SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x3596a46c), SHC(0x8bc1f6e8), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb9d759), SHC(0xf7a0dec9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x793501a9), SHC(0xd6db1254), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x54657194), SHC(0x9fc3b694), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x471cece7), SHC(0x9592675c), SHC(0x40000000), SHC(0x9126145f), SHC(0x389cea72), SHC(0x8d334625), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2924edac), SHC(0x86cafe57), SHC(0x2120fb83), SHC(0x845c8ae3), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x10b5150f), SHC(0x811855b4), SHC(0x085f2137), SHC(0x804628a7), + SHC(0x00000000), SHC(0x80000000), SHC(0xf7a0dec9), SHC(0x804628a7), SHC(0xef4aeaf1), SHC(0x811855b4), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd6db1254), SHC(0x86cafe57), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f76892f), SHC(0xf449acca), SHC(0x7ddb4bfc), SHC(0xe8ac819d), + SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x72ccb9db), SHC(0xc763158e), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x668f7c25), SHC(0xb36a1978), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x444d7aff), SHC(0x93bf30d4), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x2f6e6d16), SHC(0x891cc4c1), SHC(0x245a9d65), SHC(0x8545651a), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x01aceb7c), SHC(0x8002ceac), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xea52c166), SHC(0x81d94c8f), SHC(0xdedf047d), SHC(0x845c8ae3), + SHC(0xd3b26fb0), SHC(0x87e958a7), SHC(0xc8e5032b), SHC(0x8c7815dd), SHC(0xbe8df2ba), SHC(0x91fef880), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xab9a8e6c), SHC(0x9fc3b694), SHC(0xa326eec0), SHC(0xa7e3ff4d), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x94a6715d), SHC(0xba4944a2), SHC(0x8eb8b9a0), SHC(0xc466be4f), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x4b3c8c12), SHC(0x98722192), + SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x22be8f87), SHC(0x84ce444e), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x05067734), SHC(0x80194350), SHC(0xf5f50d67), SHC(0x80650347), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xca695b94), SHC(0x8bc1f6e8), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb0c1878b), SHC(0x9b7abc1c), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8bc1f6e8), SHC(0xca695b94), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80650347), SHC(0xf5f50d67), + SHC(0x80194350), SHC(0x05067734), SHC(0x81936daf), SHC(0x14060b68), SHC(0x84ce444e), SHC(0x22be8f87), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7eace58a), SHC(0xeda208a5), SHC(0x7aba9ae6), SHC(0xdba5629b), + SHC(0x743e0918), SHC(0xca695b94), SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x53211d18), SHC(0x9eab046f), SHC(0x444d7aff), SHC(0x93bf30d4), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x22be8f87), SHC(0x84ce444e), SHC(0x10b5150f), SHC(0x811855b4), SHC(0xfe531484), SHC(0x8002ceac), + SHC(0xebf9f498), SHC(0x81936daf), SHC(0xda0aecf9), SHC(0x85c1e80e), SHC(0xc8e5032b), SHC(0x8c7815dd), + SHC(0xb8e31319), SHC(0x9592675c), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0x9d969742), SHC(0xae26dcdf), + SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8a650cb4), SHC(0xcd790887), SHC(0x845c8ae3), SHC(0xdedf047d), + SHC(0x80e321ff), SHC(0xf0f488d9), SHC(0x800b3a91), SHC(0x0359c428), SHC(0x81d94c8f), SHC(0x15ad3e9a), + SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8d334625), SHC(0x389cea72), SHC(0x96830876), SHC(0x487fffe4), + SHC(0xa201b853), SHC(0x56e2f15d), SHC(0xaf726def), SHC(0x637984d4), SHC(0xbe8df2ba), SHC(0x6e010780), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e26b371), SHC(0xea52c166), SHC(0x78a879f4), SHC(0xd545d11c), + SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x637984d4), SHC(0xaf726def), SHC(0x54657194), SHC(0x9fc3b694), + SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x2f6e6d16), SHC(0x891cc4c1), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x05067734), SHC(0x80194350), SHC(0xef4aeaf1), SHC(0x811855b4), SHC(0xda0aecf9), SHC(0x85c1e80e), + SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb36a1978), SHC(0x997083db), SHC(0xa326eec0), SHC(0xa7e3ff4d), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x8b10f144), SHC(0xcbf00dbe), SHC(0x83f03dd6), SHC(0xe07e0c84), + SHC(0x80650347), SHC(0xf5f50d67), SHC(0x808976d1), SHC(0x0bb65336), SHC(0x845c8ae3), SHC(0x2120fb83), + SHC(0x8bc1f6e8), SHC(0x3596a46c), SHC(0x96830876), SHC(0x487fffe4), SHC(0xa45037c9), SHC(0x595132a2), + SHC(0xb4c373ee), SHC(0x678dde6e), SHC(0xc763158e), SHC(0x72ccb9db), SHC(0xdba5629b), SHC(0x7aba9ae6), + SHC(0xf0f488d9), SHC(0x7f1cde01), SHC(0x06b2f1d2), SHC(0x7fd317b4), SHC(0x1c3fd045), SHC(0x7cd80464), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x471cece7), SHC(0x9592675c), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x00000000), SHC(0x80000000), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xb8e31319), SHC(0x9592675c), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9592675c), SHC(0xb8e31319), SHC(0x89be50c3), SHC(0xcf043ab3), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80000000), SHC(0x00000000), SHC(0x8275a0c0), SHC(0x18f8b83c), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9592675c), SHC(0x471cece7), SHC(0xa57d8666), SHC(0x5a82799a), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xcf043ab3), SHC(0x7641af3d), SHC(0xe70747c4), SHC(0x7d8a5f40), + SHC(0x00000000), SHC(0x7fffffff), SHC(0x18f8b83c), SHC(0x7d8a5f40), SHC(0x30fbc54d), SHC(0x7641af3d), + SHC(0x471cece7), SHC(0x6a6d98a4), SHC(0x5a82799a), SHC(0x5a82799a), SHC(0x6a6d98a4), SHC(0x471cece7)}; + +# ifdef ENABLE_HR_MODE +#ifdef CR8_G_ADD_75MS +const Word32 RotVector_720[2 * (720 - 30)] = { + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffb0260), SHC(0xfdc41e9b), SHC(0x7fec09e3), SHC(0xfb8869ce), + SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7fb02dc6), SHC(0xf7123849), SHC(0x7f834ed0), SHC(0xf4d814a4), + SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7f0bc097), SHC(0xf06695da), SHC(0x7ec11aa5), SHC(0xee2f9369), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7e0e2e32), SHC(0xe9c5e582), SHC(0x7da5f5a5), SHC(0xe7939223), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7cb82885), SHC(0xe334cdc9), SHC(0x7c32a67e), SHC(0xe108b40d), + SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), SHC(0x7a6831ba), SHC(0xda939061), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7906c0b0), SHC(0xd653c860), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x76adf5e6), SHC(0xd00ce422), SHC(0x75d31a61), SHC(0xcdfc85bb), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x7401e4c1), SHC(0xc9e7a512), SHC(0x730baeed), SHC(0xc7e3744b), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x6ff389df), SHC(0xc1f1c224), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fec09e3), SHC(0xfb8869ce), SHC(0x7fb02dc6), SHC(0xf7123849), + SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7ec11aa5), SHC(0xee2f9369), SHC(0x7e0e2e32), SHC(0xe9c5e582), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7c32a67e), SHC(0xe108b40d), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7847d909), SHC(0xd438af17), SHC(0x76adf5e6), SHC(0xd00ce422), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x730baeed), SHC(0xc7e3744b), SHC(0x71046d3e), SHC(0xc3e85b18), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6c8cd70b), SHC(0xbc2b9b05), SHC(0x6a1de737), SHC(0xb86c5df0), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x64dd8950), SHC(0xb1320139), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x5c13539b), SHC(0xa7156f3c), SHC(0x58ea90c4), SHC(0xa3ecac65), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x5246dd49), SHC(0x9df24175), SHC(0x4ecdfec7), SHC(0x9b2276b0), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x4793a210), SHC(0x95e218c9), SHC(0x43d464fb), SHC(0x937328f5), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6b598ea3), SHC(0xba4944a2), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x637984d4), SHC(0xaf726def), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x508d9211), SHC(0x9c867b2c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x45b6bb5e), SHC(0x94a6715d), SHC(0x40000000), SHC(0x9126145f), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x340ff242), SHC(0x8b10f144), SHC(0x2ddf0040), SHC(0x88806fc4), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x06b2f1d2), SHC(0x802ce84c), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb02dc6), SHC(0xf7123849), SHC(0x7ec11aa5), SHC(0xee2f9369), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x6c8cd70b), SHC(0xbc2b9b05), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x620dbe8b), SHC(0xadb922b7), SHC(0x5c13539b), SHC(0xa7156f3c), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x4ecdfec7), SHC(0x9b2276b0), SHC(0x4793a210), SHC(0x95e218c9), + SHC(0x40000000), SHC(0x9126145f), SHC(0x381c8bb5), SHC(0x8cf45113), SHC(0x2ff31bde), SHC(0x89520a1a), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1ef74bf3), SHC(0x83cd5982), SHC(0x163a1a7e), SHC(0x81f1d1ce), + SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x04779632), SHC(0x8013f61d), SHC(0xfb8869ce), SHC(0x8013f61d), + SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe9c5e582), SHC(0x81f1d1ce), SHC(0xe108b40d), SHC(0x83cd5982), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xd00ce422), SHC(0x89520a1a), SHC(0xc7e3744b), SHC(0x8cf45113), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f834ed0), SHC(0xf4d814a4), SHC(0x7e0e2e32), SHC(0xe9c5e582), + SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7847d909), SHC(0xd438af17), SHC(0x7401e4c1), SHC(0xc9e7a512), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x68d9f964), SHC(0xb6950c1e), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x5246dd49), SHC(0x9df24175), SHC(0x496af3e2), SHC(0x9726069c), + SHC(0x40000000), SHC(0x9126145f), SHC(0x36185aee), SHC(0x8bfe1b3f), SHC(0x2bc750e9), SHC(0x87b826f7), + SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x163a1a7e), SHC(0x81f1d1ce), SHC(0x0b27eb5c), SHC(0x807cb130), + SHC(0x00000000), SHC(0x80000000), SHC(0xf4d814a4), SHC(0x807cb130), SHC(0xe9c5e582), SHC(0x81f1d1ce), + SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd438af17), SHC(0x87b826f7), SHC(0xc9e7a512), SHC(0x8bfe1b3f), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xb6950c1e), SHC(0x9726069c), SHC(0xadb922b7), SHC(0x9df24175), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9df24175), SHC(0xadb922b7), SHC(0x9726069c), SHC(0xb6950c1e), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x55a6125c), SHC(0xa0e0a15f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x40000000), SHC(0x9126145f), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0x00000000), SHC(0x80000000), SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe5632654), SHC(0x82cc0f36), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcbf00dbe), SHC(0x8b10f144), SHC(0xc0000000), SHC(0x9126145f), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0xa0e0a15f), SHC(0xaa59eda4), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x9126145f), SHC(0xc0000000), SHC(0x8b10f144), SHC(0xcbf00dbe), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x80b381ac), SHC(0xf29ecfb2), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f0bc097), SHC(0xf06695da), SHC(0x7c32a67e), SHC(0xe108b40d), + SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x68d9f964), SHC(0xb6950c1e), + SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x53f9be05), SHC(0x9f65ad2d), SHC(0x4793a210), SHC(0x95e218c9), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x2bc750e9), SHC(0x87b826f7), SHC(0x1ccb3237), SHC(0x8347d77b), + SHC(0x0d61304e), SHC(0x80b381ac), SHC(0xfdc41e9b), SHC(0x8004fda0), SHC(0xee2f9369), SHC(0x813ee55b), + SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd00ce422), SHC(0x89520a1a), SHC(0xc1f1c224), SHC(0x900c7621), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xa8b4471a), SHC(0xa263007d), SHC(0x9df24175), SHC(0xadb922b7), + SHC(0x94a6715d), SHC(0xba4944a2), SHC(0x8cf45113), SHC(0xc7e3744b), SHC(0x86f93f50), SHC(0xd653c860), + SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x807cb130), SHC(0xf4d814a4), SHC(0x8013f61d), SHC(0x04779632), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x84f56073), SHC(0x234815ba), SHC(0x8a2ce59f), SHC(0x32037a45), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ec11aa5), SHC(0xee2f9369), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6c8cd70b), SHC(0xbc2b9b05), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x4793a210), SHC(0x95e218c9), SHC(0x381c8bb5), SHC(0x8cf45113), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x163a1a7e), SHC(0x81f1d1ce), SHC(0x04779632), SHC(0x8013f61d), + SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe108b40d), SHC(0x83cd5982), SHC(0xd00ce422), SHC(0x89520a1a), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xb1320139), SHC(0x9b2276b0), SHC(0xa3ecac65), SHC(0xa7156f3c), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8efb92c2), SHC(0xc3e85b18), SHC(0x87b826f7), SHC(0xd438af17), + SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x804fd23a), SHC(0xf7123849), SHC(0x804fd23a), SHC(0x08edc7b7), + SHC(0x82cc0f36), SHC(0x1a9cd9ac), SHC(0x87b826f7), SHC(0x2bc750e9), SHC(0x8efb92c2), SHC(0x3c17a4e8), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0xa3ecac65), SHC(0x58ea90c4), SHC(0xb1320139), SHC(0x64dd8950), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x278dde6e), SHC(0x8643c7b3), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x00000000), SHC(0x80000000), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8df37f8b), SHC(0xc5e3a3a9), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x81936daf), SHC(0xebf9f498), SHC(0x80000000), SHC(0x00000000), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8df37f8b), SHC(0x3a1c5c57), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0xa57d8666), SHC(0x5a82799a), SHC(0xb4c373ee), SHC(0x678dde6e), + SHC(0xc5e3a3a9), SHC(0x720c8075), SHC(0xd8722192), SHC(0x79bc384d), SHC(0xebf9f498), SHC(0x7e6c9251), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e0e2e32), SHC(0xe9c5e582), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x620dbe8b), SHC(0xadb922b7), SHC(0x5246dd49), SHC(0x9df24175), + SHC(0x40000000), SHC(0x9126145f), SHC(0x2bc750e9), SHC(0x87b826f7), SHC(0x163a1a7e), SHC(0x81f1d1ce), + SHC(0x00000000), SHC(0x80000000), SHC(0xe9c5e582), SHC(0x81f1d1ce), SHC(0xd438af17), SHC(0x87b826f7), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xadb922b7), SHC(0x9df24175), SHC(0x9df24175), SHC(0xadb922b7), + SHC(0x9126145f), SHC(0xc0000000), SHC(0x87b826f7), SHC(0xd438af17), SHC(0x81f1d1ce), SHC(0xe9c5e582), + SHC(0x80000000), SHC(0x00000000), SHC(0x81f1d1ce), SHC(0x163a1a7e), SHC(0x87b826f7), SHC(0x2bc750e9), + SHC(0x9126145f), SHC(0x40000000), SHC(0x9df24175), SHC(0x5246dd49), SHC(0xadb922b7), SHC(0x620dbe8b), + SHC(0xc0000000), SHC(0x6ed9eba1), SHC(0xd438af17), SHC(0x7847d909), SHC(0xe9c5e582), SHC(0x7e0e2e32), + SHC(0x00000000), SHC(0x7fffffff), SHC(0x163a1a7e), SHC(0x7e0e2e32), SHC(0x2bc750e9), SHC(0x7847d909), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7da5f5a5), SHC(0xe7939223), SHC(0x76adf5e6), SHC(0xd00ce422), + SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x5c13539b), SHC(0xa7156f3c), SHC(0x496af3e2), SHC(0x9726069c), + SHC(0x340ff242), SHC(0x8b10f144), SHC(0x1ccb3237), SHC(0x8347d77b), SHC(0x04779632), SHC(0x8013f61d), + SHC(0xebf9f498), SHC(0x81936daf), SHC(0xd438af17), SHC(0x87b826f7), SHC(0xbe133b7c), SHC(0x92485786), + SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0x99c64fc5), SHC(0xb2f7b9af), SHC(0x8cf45113), SHC(0xc7e3744b), + SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x804fd23a), SHC(0xf7123849), SHC(0x80f43f69), SHC(0x0f996a26), + SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x900c7621), SHC(0x3e0e3ddc), SHC(0x9df24175), SHC(0x5246dd49), + SHC(0xaf726def), SHC(0x637984d4), SHC(0xc3e85b18), SHC(0x71046d3e), SHC(0xda939061), SHC(0x7a6831ba), + SHC(0xf29ecfb2), SHC(0x7f4c7e54), SHC(0x0b27eb5c), SHC(0x7f834ed0), SHC(0x234815ba), SHC(0x7b0a9f8d), + SHC(0x3a1c5c57), SHC(0x720c8075), SHC(0x4ecdfec7), SHC(0x64dd8950), SHC(0x609a52d3), SHC(0x53f9be05), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x4b3c8c12), SHC(0x98722192), + SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x22be8f87), SHC(0x84ce444e), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x05067734), SHC(0x80194350), SHC(0xf5f50d67), SHC(0x80650347), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xca695b94), SHC(0x8bc1f6e8), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb0c1878b), SHC(0x9b7abc1c), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8bc1f6e8), SHC(0xca695b94), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80650347), SHC(0xf5f50d67), + SHC(0x80194350), SHC(0x05067734), SHC(0x81936daf), SHC(0x14060b68), SHC(0x84ce444e), SHC(0x22be8f87), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7eace58a), SHC(0xeda208a5), SHC(0x7aba9ae6), SHC(0xdba5629b), + SHC(0x743e0918), SHC(0xca695b94), SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x53211d18), SHC(0x9eab046f), SHC(0x444d7aff), SHC(0x93bf30d4), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x22be8f87), SHC(0x84ce444e), SHC(0x10b5150f), SHC(0x811855b4), SHC(0xfe531484), SHC(0x8002ceac), + SHC(0xebf9f498), SHC(0x81936daf), SHC(0xda0aecf9), SHC(0x85c1e80e), SHC(0xc8e5032b), SHC(0x8c7815dd), + SHC(0xb8e31319), SHC(0x9592675c), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0x9d969742), SHC(0xae26dcdf), + SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8a650cb4), SHC(0xcd790887), SHC(0x845c8ae3), SHC(0xdedf047d), + SHC(0x80e321ff), SHC(0xf0f488d9), SHC(0x800b3a91), SHC(0x0359c428), SHC(0x81d94c8f), SHC(0x15ad3e9a), + SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8d334625), SHC(0x389cea72), SHC(0x96830876), SHC(0x487fffe4), + SHC(0xa201b853), SHC(0x56e2f15d), SHC(0xaf726def), SHC(0x637984d4), SHC(0xbe8df2ba), SHC(0x6e010780), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e26b371), SHC(0xea52c166), SHC(0x78a879f4), SHC(0xd545d11c), + SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x637984d4), SHC(0xaf726def), SHC(0x54657194), SHC(0x9fc3b694), + SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x2f6e6d16), SHC(0x891cc4c1), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x05067734), SHC(0x80194350), SHC(0xef4aeaf1), SHC(0x811855b4), SHC(0xda0aecf9), SHC(0x85c1e80e), + SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb36a1978), SHC(0x997083db), SHC(0xa326eec0), SHC(0xa7e3ff4d), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x8b10f144), SHC(0xcbf00dbe), SHC(0x83f03dd6), SHC(0xe07e0c84), + SHC(0x80650347), SHC(0xf5f50d67), SHC(0x808976d1), SHC(0x0bb65336), SHC(0x845c8ae3), SHC(0x2120fb83), + SHC(0x8bc1f6e8), SHC(0x3596a46c), SHC(0x96830876), SHC(0x487fffe4), SHC(0xa45037c9), SHC(0x595132a2), + SHC(0xb4c373ee), SHC(0x678dde6e), SHC(0xc763158e), SHC(0x72ccb9db), SHC(0xdba5629b), SHC(0x7aba9ae6), + SHC(0xf0f488d9), SHC(0x7f1cde01), SHC(0x06b2f1d2), SHC(0x7fd317b4), SHC(0x1c3fd045), SHC(0x7cd80464), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x471cece7), SHC(0x9592675c), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x00000000), SHC(0x80000000), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xb8e31319), SHC(0x9592675c), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9592675c), SHC(0xb8e31319), SHC(0x89be50c3), SHC(0xcf043ab3), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80000000), SHC(0x00000000), SHC(0x8275a0c0), SHC(0x18f8b83c), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9592675c), SHC(0x471cece7), SHC(0xa57d8666), SHC(0x5a82799a), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xcf043ab3), SHC(0x7641af3d), SHC(0xe70747c4), SHC(0x7d8a5f40), + SHC(0x00000000), SHC(0x7fffffff), SHC(0x18f8b83c), SHC(0x7d8a5f40), SHC(0x30fbc54d), SHC(0x7641af3d), + SHC(0x471cece7), SHC(0x6a6d98a4), SHC(0x5a82799a), SHC(0x5a82799a), SHC(0x6a6d98a4), SHC(0x471cece7), + SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), + SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), + SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0x00007fff), SHC(0xfb887fec), SHC(0xf7127fb0), + SHC(0xf29f7f4c), SHC(0xee307ec1), SHC(0xe9c67e0e), SHC(0xe5637d34), SHC(0xe1097c33), SHC(0xdcb87b0b), + SHC(0xd87279bc), SHC(0xd4397848), SHC(0xd00d76ae), SHC(0xcbf074ef), SHC(0xc7e3730c), SHC(0xc3e87104), + SHC(0x00007fff), SHC(0xf7127fb0), SHC(0xee307ec1), SHC(0xe5637d34), SHC(0xdcb87b0b), SHC(0xd4397848), + SHC(0xcbf074ef), SHC(0xc3e87104), SHC(0xbc2c6c8d), SHC(0xb4c3678e), SHC(0xadb9620e), SHC(0xa7155c13), + SHC(0xa0e155a6), SHC(0x9b224ece), SHC(0x95e24794), SHC(0x00007fff), SHC(0xf29f7f4c), SHC(0xe5637d34), + SHC(0xd87279bc), SHC(0xcbf074ef), SHC(0xc0006eda), SHC(0xb4c3678e), SHC(0xaa5a5f1f), SHC(0xa0e155a6), + SHC(0x98724b3d), SHC(0x91264000), SHC(0x8b113410), SHC(0x8644278e), SHC(0x82cc1a9d), SHC(0x80b40d61), + SHC(0x00007fff), SHC(0xee307ec1), SHC(0xdcb87b0b), SHC(0xcbf074ef), SHC(0xbc2c6c8d), SHC(0xadb9620e), + SHC(0xa0e155a6), SHC(0x95e24794), SHC(0x8cf4381d), SHC(0x8644278e), SHC(0x81f2163a), SHC(0x80140478), + SHC(0x80b4f29f), SHC(0x83cde109), SHC(0x8952d00d), SHC(0x00007fff), SHC(0xe9c67e0e), SHC(0xd4397848), + SHC(0xc0006eda), SHC(0xadb9620e), SHC(0x9df25247), SHC(0x91264000), SHC(0x87b82bc7), SHC(0x81f2163a), + SHC(0x80000000), SHC(0x81f2e9c6), SHC(0x87b8d439), SHC(0x9126c000), SHC(0x9df2adb9), SHC(0xadb99df2), + SHC(0x00007fff), SHC(0xe5637d34), SHC(0xcbf074ef), SHC(0xb4c3678e), SHC(0xa0e155a6), SHC(0x91264000), + SHC(0x8644278e), SHC(0x80b40d61), SHC(0x80b4f29f), SHC(0x8644d872), SHC(0x9126c000), SHC(0xa0e1aa5a), + SHC(0xb4c39872), SHC(0xcbf08b11), SHC(0xe56382cc), SHC(0x00007fff), SHC(0xe1097c33), SHC(0xc3e87104), + SHC(0xaa5a5f1f), SHC(0x95e24794), SHC(0x87b82bc7), SHC(0x80b40d61), SHC(0x813fee30), SHC(0x8952d00d), + SHC(0x9872b4c3), SHC(0xadb99df2), SHC(0xc7e38cf4), SHC(0xe56382cc), SHC(0x04788014), SHC(0x234884f5), + SHC(0x00007fff), SHC(0xdcb87b0b), SHC(0xbc2c6c8d), SHC(0xa0e155a6), SHC(0x8cf4381d), SHC(0x81f2163a), + SHC(0x80b4f29f), SHC(0x8952d00d), SHC(0x9b22b132), SHC(0xb4c39872), SHC(0xd43987b8), SHC(0xf7128050), + SHC(0x1a9d82cc), SHC(0x3c188efc), SHC(0x58eba3ed), SHC(0x00007fff), SHC(0xd87279bc), SHC(0xb4c3678e), + SHC(0x98724b3d), SHC(0x8644278e), SHC(0x80000000), SHC(0x8644d872), SHC(0x9872b4c3), SHC(0xb4c39872), + SHC(0xd8728644), SHC(0x00008000), SHC(0x278e8644), SHC(0x4b3d9872), SHC(0x678eb4c3), SHC(0x79bcd872), + SHC(0x00007fff), SHC(0xd4397848), SHC(0xadb9620e), SHC(0x91264000), SHC(0x81f2163a), SHC(0x81f2e9c6), + SHC(0x9126c000), SHC(0xadb99df2), SHC(0xd43987b8), SHC(0x00008000), SHC(0x2bc787b8), SHC(0x52479df2), + SHC(0x6edac000), SHC(0x7e0ee9c6), SHC(0x7e0e163a), SHC(0x00007fff), SHC(0xd00d76ae), SHC(0xa7155c13), + SHC(0x8b113410), SHC(0x80140478), SHC(0x87b8d439), SHC(0xa0e1aa5a), SHC(0xc7e38cf4), SHC(0xf7128050), + SHC(0x278e8644), SHC(0x52479df2), SHC(0x7104c3e8), SHC(0x7f4cf29f), SHC(0x7b0b2348), SHC(0x64de4ece), + SHC(0x00007fff), SHC(0xe21e7c77), SHC(0xc5e4720d), SHC(0xacdf6155), SHC(0x98724b3d), SHC(0x89be30fc), + SHC(0x81931406), SHC(0x8065f5f5), SHC(0x8644d872), SHC(0x92ddbd1f), SHC(0xa57ea57e), SHC(0xbd1f92dd), + SHC(0xd8728644), SHC(0xf5f58065), SHC(0x14068193), SHC(0x00007fff), SHC(0xdba57abb), SHC(0xba496b5a), + SHC(0x9eab5321), SHC(0x8b113410), SHC(0x811810b5), SHC(0x8193ebfa), SHC(0x8c78c8e5), SHC(0xa0e1aa5a), + SHC(0xbd1f92dd), SHC(0xdedf845d), SHC(0x035a800b), SHC(0x278e8644), SHC(0x48809683), SHC(0x637aaf72), + SHC(0x00007fff), SHC(0xd54678a8), SHC(0xaf72637a), SHC(0x92dd42e1), SHC(0x82cc1a9d), SHC(0x8118ef4b), + SHC(0x8df3c5e4), SHC(0xa7e4a327), SHC(0xcbf08b11), SHC(0xf5f58065), SHC(0x2121845d), SHC(0x48809683), + SHC(0x678eb4c3), SHC(0x7abbdba5), SHC(0x7fd306b3), SHC(0x00007fff), SHC(0xcf047642), SHC(0xa57e5a82), + SHC(0x89be30fc), SHC(0x80000000), SHC(0x89becf04), SHC(0xa57ea57e), SHC(0xcf0489be), SHC(0x00008000), + SHC(0x30fc89be), SHC(0x5a82a57e), SHC(0x7642cf04), SHC(0x7fff0000), SHC(0x764230fc), SHC(0x5a825a82), + SHC(0xe2e1004b), SHC(0x00000000), SHC(0x00000000), SHC(0x6fb076e0), SHC(0x002fba9c), SHC(0x6fb079d0), + SHC(0x8d92be50), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0xffffffff), + SHC(0x00010000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0xffffffff), SHC(0x00010000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0xeabee318), SHC(0x00000000), SHC(0x4d55545a), + SHC(0000000000), SHC(0000000000), SHC(0x00000000), SHC(0x00000000), SHC(0xffffffff), SHC(0x904f882f), + SHC(0x4d55545a), SHC(0x00000000), SHC(0x00000000), SHC(0x006f5dd8), SHC(0x40000000), SHC(0x00666004), + SHC(0x006ec0b0), SHC(0x00660000), SHC(0x006f5dd8), SHC(0x42000000), SHC(0x00665fa0), SHC(0x006ec080), + SHC(0x6fb07880), SHC(0x00660000), SHC(0x00660000), SHC(0x00309ca0), SHC(0x00000000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), + SHC(0xffffffff), SHC(0x00010000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x0d888000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), + SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), SHC(0x00000000), + SHC(0x00000170), SHC(0x00000000), SHC(0x00000000), SHC(0x6fb07880), SHC(0x6fb078a8), SHC(0x8d926000), + SHC(0x0d888000), SHC(0x8d888000), SHC(0x6fb079e0), SHC(0x00000000), SHC(0000000000), SHC(0x002f8000), + SHC(0x00000001), SHC(0x6fb07b40), SHC(0x00000000), SHC(0x6fb07b54), SHC(0x6fb07b70), SHC(0x6fb07b80), + SHC(0x6fb07b94), SHC(0x6fb07bcd), SHC(0x6fb07be6), SHC(0x6fb07c0e), SHC(0x6fb07c43), SHC(0x6fb07c4d), + SHC(0x6fb07c8f), SHC(0x6fb07d49), SHC(0x6fb07d71), SHC(0x6fb07d9e), SHC(0x6fb07daf), SHC(0x6fb07dbd), + SHC(0x6fb07dcc), SHC(0x6fb07ddf), SHC(0x6fb07de7), SHC(0x6fb07df8), SHC(0x6fb07e05), SHC(0x6fb07e45), + SHC(0x00000000), SHC(0x6fb07b18), SHC(0x6fb07e60), SHC(0x6fb07e70), SHC(0x6fb07e8f), SHC(0x6fb07ec4), + SHC(0x6fb07ee1), SHC(0x6fb07f17), SHC(0x6fb07f3e), SHC(0x6fb07f67), SHC(0x6fb07fa2), SHC(0x6fb07fdf), + SHC(0x6fb07fed), SHC(0x00000000), SHC(0x63657865), SHC(0x705f656c), SHC(0x65672f2e), SHC(0x6f526574), + SHC(0x00726f74), SHC(0x65672f2e), SHC(0x6f526574), SHC(0x00726f74), SHC(0x4f52505f), SHC(0x7070413d), + SHC(0x696d7265), SHC(0x4c454853), SHC(0x622f6e69), SHC(0x4d524554), SHC(0x322d6d72), SHC(0x00726f6c), + SHC(0x2f3d5249), SHC(0x646c6f66), SHC(0x6e2f3238), SHC(0x36737636), SHC(0x78663431), SHC(0x3031785f), + SHC(0x2f542f33), SHC(0x52505f4d), SHC(0x45565f4d), SHC(0x34343d4e), SHC(0x44575044), SHC(0x2f737265), + SHC(0x636f442f), SHC(0x6c2f7374), SHC(0x65747361), SHC(0x535f4d52), SHC(0x495f4e4f), SHC(0x34323939), + SHC(0x2d364133), SHC(0x4345382d), SHC(0x43344233), SHC(0x55003845), SHC(0x6d676c73), SHC(0x5455415f), + SHC(0x2f3d4b43), SHC(0x2f657461), SHC(0x2e6d6f63), SHC(0x616c2e65), SHC(0x64722e64), SHC(0x4b776b7a), + SHC(0x656e6574), SHC(0x3d485441), SHC(0x6d6f682f), SHC(0x69622f77), SHC(0x6c2f7273), SHC(0x6e69622f), + SHC(0x69622f72), SHC(0x2f3a6e69), SHC(0x6e696273), SHC(0x2f3a6e69), SHC(0x656d6f68), SHC(0x6e69622f), + SHC(0x31582f74), SHC(0x4c2f3a6e), SHC(0x412f7972), SHC(0x7273752f), SHC(0x70412f3a), SHC(0x6f697461), + SHC(0x61757369), SHC(0x6f696475), SHC(0x70612e65), SHC(0x6e65746e), SHC(0x756f7365), SHC(0x7070612f), + SHC(0x435f5f00), SHC(0x49656c64), SHC(0x65696669), SHC(0x70612e6d), SHC(0x6d726554), SHC(0x44575000), + SHC(0x2f737265), SHC(0x636f442f), SHC(0x6c2f7374), SHC(0x65747361), SHC(0x74706972), SHC(0x643d474e), + SHC(0x4654552e), SHC(0x465f4350), SHC(0x3078303d), SHC(0x40755c3d), SHC(0x00202477), SHC(0x56524553), + SHC(0x454d414e), SHC(0x4c564c48), SHC(0x3d454d4f), SHC(0x732f7372), SHC(0x4e474f4c), SHC(0x6d676c73), + SHC(0x59414c50), SHC(0x74617669), SHC(0x6f632f70), SHC(0x2e656c70), SHC(0x2e646863), SHC(0x53386438) + }; +#endif +const Word32 RotVector_960[2 * (480 - 60)] = { + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffd3154), SHC(0xfe531484), SHC(0x7ff4c56f), SHC(0xfca63bd8), + SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7fb9d759), SHC(0xf7a0dec9), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f76892f), SHC(0xf449acca), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7eace58a), SHC(0xeda208a5), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7e26b371), SHC(0xea52c166), SHC(0x7ddb4bfc), SHC(0xe8ac819d), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7cd80464), SHC(0xe3c02fbb), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7c0fc22a), SHC(0xe07e0c84), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x7aba9ae6), SHC(0xdba5629b), SHC(0x7a3e17f2), SHC(0xda0aecf9), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x793501a9), SHC(0xd6db1254), SHC(0x78a879f4), SHC(0xd545d11c), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x76e33b3f), SHC(0xd09192ea), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x759af34c), SHC(0xcd790887), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x743e0918), SHC(0xca695b94), SHC(0x7387ea23), SHC(0xc8e5032b), SHC(0x72ccb9db), SHC(0xc763158e), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x71474660), SHC(0xc466be4f), SHC(0x707d1443), SHC(0xc2ec7635), + SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6e010780), SHC(0xbe8df2ba), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x6c40cf2c), SHC(0xbbb28501), SHC(0x6b598ea3), SHC(0xba4944a2), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x697cf78a), SHC(0xb780001c), SHC(0x6887b5e2), SHC(0xb6201b3e), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x668f7c25), SHC(0xb36a1978), SHC(0x658c9a2d), SHC(0xb2141b02), + SHC(0x648543e4), SHC(0xb0c1878b), SHC(0x637984d4), SHC(0xaf726def), SHC(0x626968be), SHC(0xae26dcdf), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x603c496c), SHC(0xab9a8e6c), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x5dfe47ad), SHC(0xa91d0ea3), SHC(0x5cd91140), SHC(0xa7e3ff4d), SHC(0x5bafc837), SHC(0xa6aecd5e), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ff4c56f), SHC(0xfca63bd8), SHC(0x7fd317b4), SHC(0xf94d0e2e), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7ddb4bfc), SHC(0xe8ac819d), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7aba9ae6), SHC(0xdba5629b), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x78a879f4), SHC(0xd545d11c), SHC(0x777f903c), SHC(0xd220ffc0), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x7387ea23), SHC(0xc8e5032b), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x707d1443), SHC(0xc2ec7635), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x697cf78a), SHC(0xb780001c), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x637984d4), SHC(0xaf726def), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x5cd91140), SHC(0xa7e3ff4d), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x581c00b3), SHC(0xa326eec0), SHC(0x55a6125c), SHC(0xa0e0a15f), + SHC(0x53211d18), SHC(0x9eab046f), SHC(0x508d9211), SHC(0x9c867b2c), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x487fffe4), SHC(0x96830876), SHC(0x45b6bb5e), SHC(0x94a6715d), + SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x40000000), SHC(0x9126145f), SHC(0x3d1389cb), SHC(0x8f82ebbd), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x371afcd5), SHC(0x8c7815dd), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2ddf0040), SHC(0x88806fc4), SHC(0x2aba2ee4), SHC(0x8757860c), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x245a9d65), SHC(0x8545651a), SHC(0x2120fb83), SHC(0x845c8ae3), + SHC(0x1de189a6), SHC(0x838961e8), SHC(0x1a9cd9ac), SHC(0x82cc0f36), SHC(0x17537e63), SHC(0x8224b404), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x10b5150f), SHC(0x811855b4), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0x0a0af299), SHC(0x80650347), SHC(0x06b2f1d2), SHC(0x802ce84c), SHC(0x0359c428), SHC(0x800b3a91), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7f9afcb9), SHC(0xf5f50d67), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x743e0918), SHC(0xca695b94), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x6d23501b), SHC(0xbd1ec45c), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x648543e4), SHC(0xb0c1878b), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5dfe47ad), SHC(0xa91d0ea3), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x53211d18), SHC(0x9eab046f), SHC(0x4f3e7875), SHC(0x9b7abc1c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x471cece7), SHC(0x9592675c), SHC(0x42e13ba4), SHC(0x92dcafe5), + SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x3596a46c), SHC(0x8bc1f6e8), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2c4d9050), SHC(0x87e958a7), SHC(0x278dde6e), SHC(0x8643c7b3), + SHC(0x22be8f87), SHC(0x84ce444e), SHC(0x1de189a6), SHC(0x838961e8), SHC(0x18f8b83c), SHC(0x8275a0c0), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0f0b7727), SHC(0x80e321ff), SHC(0x0a0af299), SHC(0x80650347), + SHC(0x05067734), SHC(0x80194350), SHC(0x00000000), SHC(0x80000000), SHC(0xfaf988cc), SHC(0x80194350), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xf0f488d9), SHC(0x80e321ff), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xe21e765a), SHC(0x838961e8), SHC(0xdd417079), SHC(0x84ce444e), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xd3b26fb0), SHC(0x87e958a7), SHC(0xcf043ab3), SHC(0x89be50c3), + SHC(0xca695b94), SHC(0x8bc1f6e8), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xc174dbf2), SHC(0x90520d04), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb8e31319), SHC(0x9592675c), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0xb0c1878b), SHC(0x9b7abc1c), SHC(0xacdee2e8), SHC(0x9eab046f), SHC(0xa91d0ea3), SHC(0xa201b853), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6b598ea3), SHC(0xba4944a2), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x637984d4), SHC(0xaf726def), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x508d9211), SHC(0x9c867b2c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x45b6bb5e), SHC(0x94a6715d), SHC(0x40000000), SHC(0x9126145f), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x340ff242), SHC(0x8b10f144), SHC(0x2ddf0040), SHC(0x88806fc4), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x06b2f1d2), SHC(0x802ce84c), + SHC(0x00000000), SHC(0x80000000), SHC(0xf94d0e2e), SHC(0x802ce84c), SHC(0xf29ecfb2), SHC(0x80b381ac), + SHC(0xebf9f498), SHC(0x81936daf), SHC(0xe5632654), SHC(0x82cc0f36), SHC(0xdedf047d), SHC(0x845c8ae3), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xd220ffc0), SHC(0x88806fc4), SHC(0xcbf00dbe), SHC(0x8b10f144), + SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xc0000000), SHC(0x9126145f), SHC(0xba4944a2), SHC(0x94a6715d), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xaf726def), SHC(0x9c867b2c), SHC(0xaa59eda4), SHC(0xa0e0a15f), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0xa0e0a15f), SHC(0xaa59eda4), SHC(0x9c867b2c), SHC(0xaf726def), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x94a6715d), SHC(0xba4944a2), SHC(0x9126145f), SHC(0xc0000000), + SHC(0x8df37f8b), SHC(0xc5e3a3a9), SHC(0x8b10f144), SHC(0xcbf00dbe), SHC(0x88806fc4), SHC(0xd220ffc0), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x82cc0f36), SHC(0xe5632654), + SHC(0x81936daf), SHC(0xebf9f498), SHC(0x80b381ac), SHC(0xf29ecfb2), SHC(0x802ce84c), SHC(0xf94d0e2e), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb9d759), SHC(0xf7a0dec9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x793501a9), SHC(0xd6db1254), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x54657194), SHC(0x9fc3b694), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x471cece7), SHC(0x9592675c), SHC(0x40000000), SHC(0x9126145f), SHC(0x389cea72), SHC(0x8d334625), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2924edac), SHC(0x86cafe57), SHC(0x2120fb83), SHC(0x845c8ae3), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x10b5150f), SHC(0x811855b4), SHC(0x085f2137), SHC(0x804628a7), + SHC(0x00000000), SHC(0x80000000), SHC(0xf7a0dec9), SHC(0x804628a7), SHC(0xef4aeaf1), SHC(0x811855b4), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd6db1254), SHC(0x86cafe57), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc763158e), SHC(0x8d334625), SHC(0xc0000000), SHC(0x9126145f), + SHC(0xb8e31319), SHC(0x9592675c), SHC(0xb2141b02), SHC(0x9a7365d3), SHC(0xab9a8e6c), SHC(0x9fc3b694), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9fc3b694), SHC(0xab9a8e6c), SHC(0x9a7365d3), SHC(0xb2141b02), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x9126145f), SHC(0xc0000000), SHC(0x8d334625), SHC(0xc763158e), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x86cafe57), SHC(0xd6db1254), SHC(0x845c8ae3), SHC(0xdedf047d), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x811855b4), SHC(0xef4aeaf1), SHC(0x804628a7), SHC(0xf7a0dec9), + SHC(0x80000000), SHC(0x00000000), SHC(0x804628a7), SHC(0x085f2137), SHC(0x811855b4), SHC(0x10b5150f), + SHC(0x8275a0c0), SHC(0x18f8b83c), SHC(0x845c8ae3), SHC(0x2120fb83), SHC(0x86cafe57), SHC(0x2924edac), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x8d334625), SHC(0x389cea72), SHC(0x9126145f), SHC(0x40000000), + SHC(0x9592675c), SHC(0x471cece7), SHC(0x9a7365d3), SHC(0x4debe4fe), SHC(0x9fc3b694), SHC(0x54657194), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7e6c9251), SHC(0xebf9f498), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x678dde6e), SHC(0xb4c373ee), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x53211d18), SHC(0x9eab046f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x3a1c5c57), SHC(0x8df37f8b), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1de189a6), SHC(0x838961e8), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0a0af299), SHC(0x80650347), SHC(0x00000000), SHC(0x80000000), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xebf9f498), SHC(0x81936daf), SHC(0xe21e765a), SHC(0x838961e8), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb4c373ee), SHC(0x98722192), SHC(0xacdee2e8), SHC(0x9eab046f), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9eab046f), SHC(0xacdee2e8), SHC(0x98722192), SHC(0xb4c373ee), + SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8df37f8b), SHC(0xc5e3a3a9), SHC(0x89be50c3), SHC(0xcf043ab3), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x838961e8), SHC(0xe21e765a), SHC(0x81936daf), SHC(0xebf9f498), + SHC(0x80650347), SHC(0xf5f50d67), SHC(0x80000000), SHC(0x00000000), SHC(0x80650347), SHC(0x0a0af299), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x838961e8), SHC(0x1de189a6), SHC(0x8643c7b3), SHC(0x278dde6e), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x8df37f8b), SHC(0x3a1c5c57), SHC(0x92dcafe5), SHC(0x42e13ba4), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0x9eab046f), SHC(0x53211d18), SHC(0xa57d8666), SHC(0x5a82799a), + SHC(0xacdee2e8), SHC(0x6154fb91), SHC(0xb4c373ee), SHC(0x678dde6e), SHC(0xbd1ec45c), SHC(0x6d23501b), + SHC(0xc5e3a3a9), SHC(0x720c8075), SHC(0xcf043ab3), SHC(0x7641af3d), SHC(0xd8722192), SHC(0x79bc384d), + SHC(0xe21e765a), SHC(0x7c769e18), SHC(0xebf9f498), SHC(0x7e6c9251), SHC(0xf5f50d67), SHC(0x7f9afcb9), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f76892f), SHC(0xf449acca), SHC(0x7ddb4bfc), SHC(0xe8ac819d), + SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x72ccb9db), SHC(0xc763158e), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x668f7c25), SHC(0xb36a1978), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x444d7aff), SHC(0x93bf30d4), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x2f6e6d16), SHC(0x891cc4c1), SHC(0x245a9d65), SHC(0x8545651a), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x01aceb7c), SHC(0x8002ceac), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xea52c166), SHC(0x81d94c8f), SHC(0xdedf047d), SHC(0x845c8ae3), + SHC(0xd3b26fb0), SHC(0x87e958a7), SHC(0xc8e5032b), SHC(0x8c7815dd), SHC(0xbe8df2ba), SHC(0x91fef880), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xab9a8e6c), SHC(0x9fc3b694), SHC(0xa326eec0), SHC(0xa7e3ff4d), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x94a6715d), SHC(0xba4944a2), SHC(0x8eb8b9a0), SHC(0xc466be4f), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x85c1e80e), SHC(0xda0aecf9), SHC(0x82cc0f36), SHC(0xe5632654), + SHC(0x80e321ff), SHC(0xf0f488d9), SHC(0x800b3a91), SHC(0xfca63bd8), SHC(0x804628a7), SHC(0x085f2137), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x83f03dd6), SHC(0x1f81f37c), SHC(0x8757860c), SHC(0x2aba2ee4), + SHC(0x8bc1f6e8), SHC(0x3596a46c), SHC(0x9126145f), SHC(0x40000000), SHC(0x97784a1e), SHC(0x49dfe4c2), + SHC(0x9eab046f), SHC(0x53211d18), SHC(0xa6aecd5e), SHC(0x5bafc837), SHC(0xaf726def), SHC(0x637984d4), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xc2ec7635), SHC(0x707d1443), SHC(0xcd790887), SHC(0x759af34c), + SHC(0xd8722192), SHC(0x79bc384d), SHC(0xe3c02fbb), SHC(0x7cd80464), SHC(0xef4aeaf1), SHC(0x7ee7aa4c), + SHC(0xfaf988cc), SHC(0x7fe6bcb0), SHC(0x06b2f1d2), SHC(0x7fd317b4), SHC(0x125df75b), SHC(0x7eace58a), + SHC(0x1de189a6), SHC(0x7c769e18), SHC(0x2924edac), SHC(0x793501a9), SHC(0x340ff242), SHC(0x74ef0ebc), + SHC(0x3e8b240e), SHC(0x6fadf2fc), SHC(0x487fffe4), SHC(0x697cf78a), SHC(0x51d92321), SHC(0x626968be)}; +# endif + +#ifdef ENABLE_FFT_30X16 +/* Twiddle coefficients for 30x16 FFTs, generated by fft_tables.py */ +# ifdef ENABLE_HR_MODE +const Word32 RotVector_30_16[2 * (480 - 30)] = { + + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffd3154), SHC(0xfe531484), SHC(0x7ff4c56f), SHC(0xfca63bd8), + SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7fb9d759), SHC(0xf7a0dec9), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f76892f), SHC(0xf449acca), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7eace58a), SHC(0xeda208a5), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7e26b371), SHC(0xea52c166), SHC(0x7ddb4bfc), SHC(0xe8ac819d), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7cd80464), SHC(0xe3c02fbb), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7c0fc22a), SHC(0xe07e0c84), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x7aba9ae6), SHC(0xdba5629b), SHC(0x7a3e17f2), SHC(0xda0aecf9), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x793501a9), SHC(0xd6db1254), SHC(0x78a879f4), SHC(0xd545d11c), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x76e33b3f), SHC(0xd09192ea), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ff4c56f), SHC(0xfca63bd8), SHC(0x7fd317b4), SHC(0xf94d0e2e), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7ddb4bfc), SHC(0xe8ac819d), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7aba9ae6), SHC(0xdba5629b), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x78a879f4), SHC(0xd545d11c), SHC(0x777f903c), SHC(0xd220ffc0), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x7387ea23), SHC(0xc8e5032b), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x707d1443), SHC(0xc2ec7635), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x697cf78a), SHC(0xb780001c), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x637984d4), SHC(0xaf726def), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x5cd91140), SHC(0xa7e3ff4d), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7f9afcb9), SHC(0xf5f50d67), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x743e0918), SHC(0xca695b94), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x6d23501b), SHC(0xbd1ec45c), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x648543e4), SHC(0xb0c1878b), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5dfe47ad), SHC(0xa91d0ea3), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x53211d18), SHC(0x9eab046f), SHC(0x4f3e7875), SHC(0x9b7abc1c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x471cece7), SHC(0x9592675c), SHC(0x42e13ba4), SHC(0x92dcafe5), + SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x3596a46c), SHC(0x8bc1f6e8), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6b598ea3), SHC(0xba4944a2), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x637984d4), SHC(0xaf726def), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x508d9211), SHC(0x9c867b2c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x45b6bb5e), SHC(0x94a6715d), SHC(0x40000000), SHC(0x9126145f), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x340ff242), SHC(0x8b10f144), SHC(0x2ddf0040), SHC(0x88806fc4), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x06b2f1d2), SHC(0x802ce84c), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb9d759), SHC(0xf7a0dec9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x793501a9), SHC(0xd6db1254), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x54657194), SHC(0x9fc3b694), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x471cece7), SHC(0x9592675c), SHC(0x40000000), SHC(0x9126145f), SHC(0x389cea72), SHC(0x8d334625), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2924edac), SHC(0x86cafe57), SHC(0x2120fb83), SHC(0x845c8ae3), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x10b5150f), SHC(0x811855b4), SHC(0x085f2137), SHC(0x804628a7), + SHC(0x00000000), SHC(0x80000000), SHC(0xf7a0dec9), SHC(0x804628a7), SHC(0xef4aeaf1), SHC(0x811855b4), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd6db1254), SHC(0x86cafe57), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7e6c9251), SHC(0xebf9f498), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x678dde6e), SHC(0xb4c373ee), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x53211d18), SHC(0x9eab046f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x3a1c5c57), SHC(0x8df37f8b), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1de189a6), SHC(0x838961e8), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0a0af299), SHC(0x80650347), SHC(0x00000000), SHC(0x80000000), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xebf9f498), SHC(0x81936daf), SHC(0xe21e765a), SHC(0x838961e8), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb4c373ee), SHC(0x98722192), SHC(0xacdee2e8), SHC(0x9eab046f), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f76892f), SHC(0xf449acca), SHC(0x7ddb4bfc), SHC(0xe8ac819d), + SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x72ccb9db), SHC(0xc763158e), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x668f7c25), SHC(0xb36a1978), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x444d7aff), SHC(0x93bf30d4), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x2f6e6d16), SHC(0x891cc4c1), SHC(0x245a9d65), SHC(0x8545651a), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x01aceb7c), SHC(0x8002ceac), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xea52c166), SHC(0x81d94c8f), SHC(0xdedf047d), SHC(0x845c8ae3), + SHC(0xd3b26fb0), SHC(0x87e958a7), SHC(0xc8e5032b), SHC(0x8c7815dd), SHC(0xbe8df2ba), SHC(0x91fef880), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xab9a8e6c), SHC(0x9fc3b694), SHC(0xa326eec0), SHC(0xa7e3ff4d), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x94a6715d), SHC(0xba4944a2), SHC(0x8eb8b9a0), SHC(0xc466be4f), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x55a6125c), SHC(0xa0e0a15f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x40000000), SHC(0x9126145f), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0x00000000), SHC(0x80000000), SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe5632654), SHC(0x82cc0f36), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcbf00dbe), SHC(0x8b10f144), SHC(0xc0000000), SHC(0x9126145f), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0xa0e0a15f), SHC(0xaa59eda4), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x9126145f), SHC(0xc0000000), SHC(0x8b10f144), SHC(0xcbf00dbe), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x80b381ac), SHC(0xf29ecfb2), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x4b3c8c12), SHC(0x98722192), + SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x22be8f87), SHC(0x84ce444e), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x05067734), SHC(0x80194350), SHC(0xf5f50d67), SHC(0x80650347), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xca695b94), SHC(0x8bc1f6e8), + SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb0c1878b), SHC(0x9b7abc1c), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8bc1f6e8), SHC(0xca695b94), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80650347), SHC(0xf5f50d67), + SHC(0x80194350), SHC(0x05067734), SHC(0x81936daf), SHC(0x14060b68), SHC(0x84ce444e), SHC(0x22be8f87), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x658c9a2d), SHC(0xb2141b02), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x40000000), SHC(0x9126145f), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x10b5150f), SHC(0x811855b4), + SHC(0x00000000), SHC(0x80000000), SHC(0xef4aeaf1), SHC(0x811855b4), SHC(0xdedf047d), SHC(0x845c8ae3), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc0000000), SHC(0x9126145f), SHC(0xb2141b02), SHC(0x9a7365d3), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9a7365d3), SHC(0xb2141b02), SHC(0x9126145f), SHC(0xc0000000), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x811855b4), SHC(0xef4aeaf1), + SHC(0x80000000), SHC(0x00000000), SHC(0x811855b4), SHC(0x10b5150f), SHC(0x845c8ae3), SHC(0x2120fb83), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9126145f), SHC(0x40000000), SHC(0x9a7365d3), SHC(0x4debe4fe), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7eace58a), SHC(0xeda208a5), SHC(0x7aba9ae6), SHC(0xdba5629b), + SHC(0x743e0918), SHC(0xca695b94), SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x53211d18), SHC(0x9eab046f), SHC(0x444d7aff), SHC(0x93bf30d4), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x22be8f87), SHC(0x84ce444e), SHC(0x10b5150f), SHC(0x811855b4), SHC(0xfe531484), SHC(0x8002ceac), + SHC(0xebf9f498), SHC(0x81936daf), SHC(0xda0aecf9), SHC(0x85c1e80e), SHC(0xc8e5032b), SHC(0x8c7815dd), + SHC(0xb8e31319), SHC(0x9592675c), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0x9d969742), SHC(0xae26dcdf), + SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8a650cb4), SHC(0xcd790887), SHC(0x845c8ae3), SHC(0xdedf047d), + SHC(0x80e321ff), SHC(0xf0f488d9), SHC(0x800b3a91), SHC(0x0359c428), SHC(0x81d94c8f), SHC(0x15ad3e9a), + SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8d334625), SHC(0x389cea72), SHC(0x96830876), SHC(0x487fffe4), + SHC(0xa201b853), SHC(0x56e2f15d), SHC(0xaf726def), SHC(0x637984d4), SHC(0xbe8df2ba), SHC(0x6e010780), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x278dde6e), SHC(0x8643c7b3), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x00000000), SHC(0x80000000), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8df37f8b), SHC(0xc5e3a3a9), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x81936daf), SHC(0xebf9f498), SHC(0x80000000), SHC(0x00000000), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8df37f8b), SHC(0x3a1c5c57), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0xa57d8666), SHC(0x5a82799a), SHC(0xb4c373ee), SHC(0x678dde6e), + SHC(0xc5e3a3a9), SHC(0x720c8075), SHC(0xd8722192), SHC(0x79bc384d), SHC(0xebf9f498), SHC(0x7e6c9251), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e26b371), SHC(0xea52c166), SHC(0x78a879f4), SHC(0xd545d11c), + SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x637984d4), SHC(0xaf726def), SHC(0x54657194), SHC(0x9fc3b694), + SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x2f6e6d16), SHC(0x891cc4c1), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x05067734), SHC(0x80194350), SHC(0xef4aeaf1), SHC(0x811855b4), SHC(0xda0aecf9), SHC(0x85c1e80e), + SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb36a1978), SHC(0x997083db), SHC(0xa326eec0), SHC(0xa7e3ff4d), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x8b10f144), SHC(0xcbf00dbe), SHC(0x83f03dd6), SHC(0xe07e0c84), + SHC(0x80650347), SHC(0xf5f50d67), SHC(0x808976d1), SHC(0x0bb65336), SHC(0x845c8ae3), SHC(0x2120fb83), + SHC(0x8bc1f6e8), SHC(0x3596a46c), SHC(0x96830876), SHC(0x487fffe4), SHC(0xa45037c9), SHC(0x595132a2), + SHC(0xb4c373ee), SHC(0x678dde6e), SHC(0xc763158e), SHC(0x72ccb9db), SHC(0xdba5629b), SHC(0x7aba9ae6), + SHC(0xf0f488d9), SHC(0x7f1cde01), SHC(0x06b2f1d2), SHC(0x7fd317b4), SHC(0x1c3fd045), SHC(0x7cd80464), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ddb4bfc), SHC(0xe8ac819d), SHC(0x777f903c), SHC(0xd220ffc0), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x245a9d65), SHC(0x8545651a), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xc8e5032b), SHC(0x8c7815dd), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xa326eec0), SHC(0xa7e3ff4d), SHC(0x94a6715d), SHC(0xba4944a2), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x800b3a91), SHC(0xfca63bd8), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8757860c), SHC(0x2aba2ee4), SHC(0x9126145f), SHC(0x40000000), + SHC(0x9eab046f), SHC(0x53211d18), SHC(0xaf726def), SHC(0x637984d4), SHC(0xc2ec7635), SHC(0x707d1443), + SHC(0xd8722192), SHC(0x79bc384d), SHC(0xef4aeaf1), SHC(0x7ee7aa4c), SHC(0x06b2f1d2), SHC(0x7fd317b4), + SHC(0x1de189a6), SHC(0x7c769e18), SHC(0x340ff242), SHC(0x74ef0ebc), SHC(0x487fffe4), SHC(0x697cf78a), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x471cece7), SHC(0x9592675c), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x00000000), SHC(0x80000000), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xb8e31319), SHC(0x9592675c), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9592675c), SHC(0xb8e31319), SHC(0x89be50c3), SHC(0xcf043ab3), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80000000), SHC(0x00000000), SHC(0x8275a0c0), SHC(0x18f8b83c), + SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9592675c), SHC(0x471cece7), SHC(0xa57d8666), SHC(0x5a82799a), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xcf043ab3), SHC(0x7641af3d), SHC(0xe70747c4), SHC(0x7d8a5f40), + SHC(0x00000000), SHC(0x7fffffff), SHC(0x18f8b83c), SHC(0x7d8a5f40), SHC(0x30fbc54d), SHC(0x7641af3d), + SHC(0x471cece7), SHC(0x6a6d98a4), SHC(0x5a82799a), SHC(0x5a82799a), SHC(0x6a6d98a4), SHC(0x471cece7)}; +# endif +#endif + +# ifdef ENABLE_HR_MODE +const Word32 RotVector_360[2 * (360 - 30)] = { +# else +const Word16 RotVector_360[2 * (360 - 30)] = { +# endif + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffb0260), SHC(0xfdc41e9b), SHC(0x7fec09e3), SHC(0xfb8869ce), + SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7fb02dc6), SHC(0xf7123849), SHC(0x7f834ed0), SHC(0xf4d814a4), + SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7f0bc097), SHC(0xf06695da), SHC(0x7ec11aa5), SHC(0xee2f9369), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7e0e2e32), SHC(0xe9c5e582), SHC(0x7da5f5a5), SHC(0xe7939223), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7cb82885), SHC(0xe334cdc9), SHC(0x7c32a67e), SHC(0xe108b40d), + SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), SHC(0x7a6831ba), SHC(0xda939061), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7906c0b0), SHC(0xd653c860), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x76adf5e6), SHC(0xd00ce422), SHC(0x75d31a61), SHC(0xcdfc85bb), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x7401e4c1), SHC(0xc9e7a512), SHC(0x730baeed), SHC(0xc7e3744b), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x6ff389df), SHC(0xc1f1c224), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fec09e3), SHC(0xfb8869ce), SHC(0x7fb02dc6), SHC(0xf7123849), + SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7ec11aa5), SHC(0xee2f9369), SHC(0x7e0e2e32), SHC(0xe9c5e582), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7c32a67e), SHC(0xe108b40d), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7847d909), SHC(0xd438af17), SHC(0x76adf5e6), SHC(0xd00ce422), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x730baeed), SHC(0xc7e3744b), SHC(0x71046d3e), SHC(0xc3e85b18), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6c8cd70b), SHC(0xbc2b9b05), SHC(0x6a1de737), SHC(0xb86c5df0), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x64dd8950), SHC(0xb1320139), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x5c13539b), SHC(0xa7156f3c), SHC(0x58ea90c4), SHC(0xa3ecac65), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x5246dd49), SHC(0x9df24175), SHC(0x4ecdfec7), SHC(0x9b2276b0), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x4793a210), SHC(0x95e218c9), SHC(0x43d464fb), SHC(0x937328f5), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fd317b4), SHC(0xf94d0e2e), SHC(0x7f4c7e54), SHC(0xf29ecfb2), + SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7ba3751d), SHC(0xdedf047d), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6b598ea3), SHC(0xba4944a2), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x637984d4), SHC(0xaf726def), SHC(0x5f1f5ea1), SHC(0xaa59eda4), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x508d9211), SHC(0x9c867b2c), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x45b6bb5e), SHC(0x94a6715d), SHC(0x40000000), SHC(0x9126145f), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x340ff242), SHC(0x8b10f144), SHC(0x2ddf0040), SHC(0x88806fc4), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x06b2f1d2), SHC(0x802ce84c), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb02dc6), SHC(0xf7123849), SHC(0x7ec11aa5), SHC(0xee2f9369), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x6c8cd70b), SHC(0xbc2b9b05), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x620dbe8b), SHC(0xadb922b7), SHC(0x5c13539b), SHC(0xa7156f3c), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x4ecdfec7), SHC(0x9b2276b0), SHC(0x4793a210), SHC(0x95e218c9), + SHC(0x40000000), SHC(0x9126145f), SHC(0x381c8bb5), SHC(0x8cf45113), SHC(0x2ff31bde), SHC(0x89520a1a), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1ef74bf3), SHC(0x83cd5982), SHC(0x163a1a7e), SHC(0x81f1d1ce), + SHC(0x0d61304e), SHC(0x80b381ac), SHC(0x04779632), SHC(0x8013f61d), SHC(0xfb8869ce), SHC(0x8013f61d), + SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe9c5e582), SHC(0x81f1d1ce), SHC(0xe108b40d), SHC(0x83cd5982), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xd00ce422), SHC(0x89520a1a), SHC(0xc7e3744b), SHC(0x8cf45113), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f834ed0), SHC(0xf4d814a4), SHC(0x7e0e2e32), SHC(0xe9c5e582), + SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7847d909), SHC(0xd438af17), SHC(0x7401e4c1), SHC(0xc9e7a512), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x68d9f964), SHC(0xb6950c1e), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x5246dd49), SHC(0x9df24175), SHC(0x496af3e2), SHC(0x9726069c), + SHC(0x40000000), SHC(0x9126145f), SHC(0x36185aee), SHC(0x8bfe1b3f), SHC(0x2bc750e9), SHC(0x87b826f7), + SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x163a1a7e), SHC(0x81f1d1ce), SHC(0x0b27eb5c), SHC(0x807cb130), + SHC(0x00000000), SHC(0x80000000), SHC(0xf4d814a4), SHC(0x807cb130), SHC(0xe9c5e582), SHC(0x81f1d1ce), + SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd438af17), SHC(0x87b826f7), SHC(0xc9e7a512), SHC(0x8bfe1b3f), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xb6950c1e), SHC(0x9726069c), SHC(0xadb922b7), SHC(0x9df24175), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9df24175), SHC(0xadb922b7), SHC(0x9726069c), SHC(0xb6950c1e), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f4c7e54), SHC(0xf29ecfb2), SHC(0x7d33f0ca), SHC(0xe5632654), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x55a6125c), SHC(0xa0e0a15f), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x40000000), SHC(0x9126145f), SHC(0x340ff242), SHC(0x8b10f144), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1a9cd9ac), SHC(0x82cc0f36), SHC(0x0d61304e), SHC(0x80b381ac), + SHC(0x00000000), SHC(0x80000000), SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe5632654), SHC(0x82cc0f36), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xcbf00dbe), SHC(0x8b10f144), SHC(0xc0000000), SHC(0x9126145f), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0xa0e0a15f), SHC(0xaa59eda4), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x9126145f), SHC(0xc0000000), SHC(0x8b10f144), SHC(0xcbf00dbe), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x80b381ac), SHC(0xf29ecfb2), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f0bc097), SHC(0xf06695da), SHC(0x7c32a67e), SHC(0xe108b40d), + SHC(0x777f903c), SHC(0xd220ffc0), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x68d9f964), SHC(0xb6950c1e), + SHC(0x5f1f5ea1), SHC(0xaa59eda4), SHC(0x53f9be05), SHC(0x9f65ad2d), SHC(0x4793a210), SHC(0x95e218c9), + SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x2bc750e9), SHC(0x87b826f7), SHC(0x1ccb3237), SHC(0x8347d77b), + SHC(0x0d61304e), SHC(0x80b381ac), SHC(0xfdc41e9b), SHC(0x8004fda0), SHC(0xee2f9369), SHC(0x813ee55b), + SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd00ce422), SHC(0x89520a1a), SHC(0xc1f1c224), SHC(0x900c7621), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xa8b4471a), SHC(0xa263007d), SHC(0x9df24175), SHC(0xadb922b7), + SHC(0x94a6715d), SHC(0xba4944a2), SHC(0x8cf45113), SHC(0xc7e3744b), SHC(0x86f93f50), SHC(0xd653c860), + SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x807cb130), SHC(0xf4d814a4), SHC(0x8013f61d), SHC(0x04779632), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x84f56073), SHC(0x234815ba), SHC(0x8a2ce59f), SHC(0x32037a45), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ec11aa5), SHC(0xee2f9369), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6c8cd70b), SHC(0xbc2b9b05), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x4793a210), SHC(0x95e218c9), SHC(0x381c8bb5), SHC(0x8cf45113), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x163a1a7e), SHC(0x81f1d1ce), SHC(0x04779632), SHC(0x8013f61d), + SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe108b40d), SHC(0x83cd5982), SHC(0xd00ce422), SHC(0x89520a1a), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xb1320139), SHC(0x9b2276b0), SHC(0xa3ecac65), SHC(0xa7156f3c), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8efb92c2), SHC(0xc3e85b18), SHC(0x87b826f7), SHC(0xd438af17), + SHC(0x82cc0f36), SHC(0xe5632654), SHC(0x804fd23a), SHC(0xf7123849), SHC(0x804fd23a), SHC(0x08edc7b7), + SHC(0x82cc0f36), SHC(0x1a9cd9ac), SHC(0x87b826f7), SHC(0x2bc750e9), SHC(0x8efb92c2), SHC(0x3c17a4e8), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0xa3ecac65), SHC(0x58ea90c4), SHC(0xb1320139), SHC(0x64dd8950), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x278dde6e), SHC(0x8643c7b3), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x00000000), SHC(0x80000000), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8df37f8b), SHC(0xc5e3a3a9), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x81936daf), SHC(0xebf9f498), SHC(0x80000000), SHC(0x00000000), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x8df37f8b), SHC(0x3a1c5c57), + SHC(0x98722192), SHC(0x4b3c8c12), SHC(0xa57d8666), SHC(0x5a82799a), SHC(0xb4c373ee), SHC(0x678dde6e), + SHC(0xc5e3a3a9), SHC(0x720c8075), SHC(0xd8722192), SHC(0x79bc384d), SHC(0xebf9f498), SHC(0x7e6c9251), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e0e2e32), SHC(0xe9c5e582), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x620dbe8b), SHC(0xadb922b7), SHC(0x5246dd49), SHC(0x9df24175), + SHC(0x40000000), SHC(0x9126145f), SHC(0x2bc750e9), SHC(0x87b826f7), SHC(0x163a1a7e), SHC(0x81f1d1ce), + SHC(0x00000000), SHC(0x80000000), SHC(0xe9c5e582), SHC(0x81f1d1ce), SHC(0xd438af17), SHC(0x87b826f7), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xadb922b7), SHC(0x9df24175), SHC(0x9df24175), SHC(0xadb922b7), + SHC(0x9126145f), SHC(0xc0000000), SHC(0x87b826f7), SHC(0xd438af17), SHC(0x81f1d1ce), SHC(0xe9c5e582), + SHC(0x80000000), SHC(0x00000000), SHC(0x81f1d1ce), SHC(0x163a1a7e), SHC(0x87b826f7), SHC(0x2bc750e9), + SHC(0x9126145f), SHC(0x40000000), SHC(0x9df24175), SHC(0x5246dd49), SHC(0xadb922b7), SHC(0x620dbe8b), + SHC(0xc0000000), SHC(0x6ed9eba1), SHC(0xd438af17), SHC(0x7847d909), SHC(0xe9c5e582), SHC(0x7e0e2e32), + SHC(0x00000000), SHC(0x7fffffff), SHC(0x163a1a7e), SHC(0x7e0e2e32), SHC(0x2bc750e9), SHC(0x7847d909), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7da5f5a5), SHC(0xe7939223), SHC(0x76adf5e6), SHC(0xd00ce422), + SHC(0x6b598ea3), SHC(0xba4944a2), SHC(0x5c13539b), SHC(0xa7156f3c), SHC(0x496af3e2), SHC(0x9726069c), + SHC(0x340ff242), SHC(0x8b10f144), SHC(0x1ccb3237), SHC(0x8347d77b), SHC(0x04779632), SHC(0x8013f61d), + SHC(0xebf9f498), SHC(0x81936daf), SHC(0xd438af17), SHC(0x87b826f7), SHC(0xbe133b7c), SHC(0x92485786), + SHC(0xaa59eda4), SHC(0xa0e0a15f), SHC(0x99c64fc5), SHC(0xb2f7b9af), SHC(0x8cf45113), SHC(0xc7e3744b), + SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x804fd23a), SHC(0xf7123849), SHC(0x80f43f69), SHC(0x0f996a26), + SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x900c7621), SHC(0x3e0e3ddc), SHC(0x9df24175), SHC(0x5246dd49), + SHC(0xaf726def), SHC(0x637984d4), SHC(0xc3e85b18), SHC(0x71046d3e), SHC(0xda939061), SHC(0x7a6831ba), + SHC(0xf29ecfb2), SHC(0x7f4c7e54), SHC(0x0b27eb5c), SHC(0x7f834ed0), SHC(0x234815ba), SHC(0x7b0a9f8d), + SHC(0x3a1c5c57), SHC(0x720c8075), SHC(0x4ecdfec7), SHC(0x64dd8950), SHC(0x609a52d3), SHC(0x53f9be05)}; + +# ifdef ENABLE_HR_MODE +const Word32 RotVector_320[2 * (320 - 20)] = { +# else +const Word16 RotVector_320[2 * (320 - 20)] = { +# endif + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7f9afcb9), SHC(0xf5f50d67), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x743e0918), SHC(0xca695b94), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x6d23501b), SHC(0xbd1ec45c), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x648543e4), SHC(0xb0c1878b), + SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5dfe47ad), SHC(0xa91d0ea3), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x720c8075), SHC(0xc5e3a3a9), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x6154fb91), SHC(0xacdee2e8), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x53211d18), SHC(0x9eab046f), SHC(0x4b3c8c12), SHC(0x98722192), + SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x1de189a6), SHC(0x838961e8), SHC(0x14060b68), SHC(0x81936daf), + SHC(0x0a0af299), SHC(0x80650347), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f1cde01), SHC(0xf0f488d9), + SHC(0x7c769e18), SHC(0xe21e765a), SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x720c8075), SHC(0xc5e3a3a9), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x56e2f15d), SHC(0xa201b853), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x22be8f87), SHC(0x84ce444e), SHC(0x14060b68), SHC(0x81936daf), SHC(0x05067734), SHC(0x80194350), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xd8722192), SHC(0x8643c7b3), + SHC(0xca695b94), SHC(0x8bc1f6e8), SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xb0c1878b), SHC(0x9b7abc1c), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x79bc384d), SHC(0xd8722192), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x4b3c8c12), SHC(0x98722192), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x278dde6e), SHC(0x8643c7b3), + SHC(0x14060b68), SHC(0x81936daf), SHC(0x00000000), SHC(0x80000000), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8df37f8b), SHC(0xc5e3a3a9), + SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x81936daf), SHC(0xebf9f498), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x471cece7), SHC(0x9592675c), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x00000000), SHC(0x80000000), SHC(0xe70747c4), SHC(0x8275a0c0), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xb8e31319), SHC(0x9592675c), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x8275a0c0), SHC(0xe70747c4), + SHC(0x80000000), SHC(0x00000000), SHC(0x8275a0c0), SHC(0x18f8b83c), SHC(0x89be50c3), SHC(0x30fbc54d), + SHC(0x9592675c), SHC(0x471cece7), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x4b3c8c12), SHC(0x98722192), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x14060b68), SHC(0x81936daf), SHC(0xf5f50d67), SHC(0x80650347), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x8643c7b3), SHC(0xd8722192), SHC(0x80650347), SHC(0xf5f50d67), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x98722192), SHC(0x4b3c8c12), + SHC(0xacdee2e8), SHC(0x6154fb91), SHC(0xc5e3a3a9), SHC(0x720c8075), SHC(0xe21e765a), SHC(0x7c769e18), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x6d23501b), SHC(0xbd1ec45c), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x18f8b83c), SHC(0x8275a0c0), + SHC(0xf5f50d67), SHC(0x80650347), SHC(0xd3b26fb0), SHC(0x87e958a7), SHC(0xb4c373ee), SHC(0x98722192), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x80e321ff), SHC(0xf0f488d9), + SHC(0x81936daf), SHC(0x14060b68), SHC(0x8bc1f6e8), SHC(0x3596a46c), SHC(0x9eab046f), SHC(0x53211d18), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xd8722192), SHC(0x79bc384d), SHC(0xfaf988cc), SHC(0x7fe6bcb0), + SHC(0x1de189a6), SHC(0x7c769e18), SHC(0x3e8b240e), SHC(0x6fadf2fc), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7ff9af04), SHC(0xfd7ca4a6), SHC(0x7fe6bcb0), SHC(0xfaf988cc), SHC(0x7fc72ae2), SHC(0xf876ebe8), + SHC(0x7f9afcb9), SHC(0xf5f50d67), SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7f1cde01), SHC(0xf0f488d9), + SHC(0x7ecaf9e5), SHC(0xee76612d), SHC(0x7e6c9251), SHC(0xebf9f498), SHC(0x7e01b096), SHC(0xe97f81eb), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7d06aa16), SHC(0xe4918486), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x7bda497d), SHC(0xdfae5b23), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x7a7d055b), SHC(0xdad7f3a2), + SHC(0x79bc384d), SHC(0xd8722192), SHC(0x78ef678f), SHC(0xd61036db), SHC(0x7816a759), SHC(0xd3b26fb0), + SHC(0x77320d0d), SHC(0xd15907d9), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fc72ae2), SHC(0xf876ebe8), + SHC(0x7f1cde01), SHC(0xf0f488d9), SHC(0x7e01b096), SHC(0xe97f81eb), SHC(0x7c769e18), SHC(0xe21e765a), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x7545a5a0), SHC(0xccb44322), + SHC(0x720c8075), SHC(0xc5e3a3a9), SHC(0x6e6e1492), SHC(0xbf469e83), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x660e9a6a), SHC(0xb2beadcc), SHC(0x6154fb91), SHC(0xacdee2e8), SHC(0x5c44ee40), SHC(0xa748e9ce), + SHC(0x56e2f15d), SHC(0xa201b853), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x4b3c8c12), SHC(0x98722192), + SHC(0x45027c0c), SHC(0x943239c7), SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x37dc420c), SHC(0x8cd50c59), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x70e2cbc6), SHC(0xc3a94590), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x471cece7), SHC(0x9592675c), SHC(0x3c56ba70), SHC(0x8f1d343a), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x25280c5e), SHC(0x8582faa5), SHC(0x18f8b83c), SHC(0x8275a0c0), + SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0x00000000), SHC(0x80000000), SHC(0xf3742ca2), SHC(0x809dc971), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdad7f3a2), SHC(0x8582faa5), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7ecaf9e5), SHC(0xee76612d), SHC(0x7b31bbb2), SHC(0xdd417079), SHC(0x7545a5a0), SHC(0xccb44322), + SHC(0x6d23501b), SHC(0xbd1ec45c), SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x56e2f15d), SHC(0xa201b853), + SHC(0x4930590f), SHC(0x96fd15e3), SHC(0x3a1c5c57), SHC(0x8df37f8b), SHC(0x29efc925), SHC(0x87109871), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x07891418), SHC(0x8038d51e), SHC(0xf5f50d67), SHC(0x80650347), + SHC(0xe4918486), SHC(0x82f955ea), SHC(0xd3b26fb0), SHC(0x87e958a7), SHC(0xc3a94590), SHC(0x8f1d343a), + SHC(0xb4c373ee), SHC(0x98722192), SHC(0xa748e9ce), SHC(0xa3bb11c0), SHC(0x9b7abc1c), SHC(0xb0c1878b), + SHC(0x9191eb6e), SHC(0xbf469e83), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e01b096), SHC(0xe97f81eb), + SHC(0x7816a759), SHC(0xd3b26fb0), SHC(0x6e6e1492), SHC(0xbf469e83), SHC(0x6154fb91), SHC(0xacdee2e8), + SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x3e8b240e), SHC(0x90520d04), SHC(0x29efc925), SHC(0x87109871), + SHC(0x14060b68), SHC(0x81936daf), SHC(0xfd7ca4a6), SHC(0x800650fc), SHC(0xe70747c4), SHC(0x8275a0c0), + SHC(0xd15907d9), SHC(0x88cdf2f3), SHC(0xbd1ec45c), SHC(0x92dcafe5), SHC(0xaaf9c6af), SHC(0xa051a5ab), + SHC(0x9b7abc1c), SHC(0xb0c1878b), SHC(0x8f1d343a), SHC(0xc3a94590), SHC(0x8643c7b3), SHC(0xd8722192), + SHC(0x8135061b), SHC(0xee76612d), SHC(0x80194350), SHC(0x05067734), SHC(0x82f955ea), SHC(0x1b6e7b7a), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7d06aa16), SHC(0xe4918486), SHC(0x743e0918), SHC(0xca695b94), + SHC(0x660e9a6a), SHC(0xb2beadcc), SHC(0x53211d18), SHC(0x9eab046f), SHC(0x3c56ba70), SHC(0x8f1d343a), + SHC(0x22be8f87), SHC(0x84ce444e), SHC(0x07891418), SHC(0x8038d51e), SHC(0xebf9f498), SHC(0x81936daf), + SHC(0xd15907d9), SHC(0x88cdf2f3), SHC(0xb8e31319), SHC(0x9592675c), SHC(0xa3bb11c0), SHC(0xa748e9ce), + SHC(0x92dcafe5), SHC(0xbd1ec45c), SHC(0x87109871), SHC(0xd61036db), SHC(0x80e321ff), SHC(0xf0f488d9), + SHC(0x809dc971), SHC(0x0c8bd35e), SHC(0x8643c7b3), SHC(0x278dde6e), SHC(0x9191eb6e), SHC(0x40b9617d), + SHC(0xa201b853), SHC(0x56e2f15d), SHC(0xb6cfa6f1), SHC(0x6902ea1d), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7bda497d), SHC(0xdfae5b23), SHC(0x6fadf2fc), SHC(0xc174dbf2), SHC(0x5c44ee40), SHC(0xa748e9ce), + SHC(0x42e13ba4), SHC(0x92dcafe5), SHC(0x25280c5e), SHC(0x8582faa5), SHC(0x05067734), SHC(0x80194350), + SHC(0xe4918486), SHC(0x82f955ea), SHC(0xc5e3a3a9), SHC(0x8df37f8b), SHC(0xaaf9c6af), SHC(0xa051a5ab), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x87109871), SHC(0xd61036db), SHC(0x80650347), SHC(0xf5f50d67), + SHC(0x81fe4f6a), SHC(0x16807e15), SHC(0x8bc1f6e8), SHC(0x3596a46c), SHC(0x9d0dfe54), SHC(0x5133cc94), + SHC(0xb4c373ee), SHC(0x678dde6e), SHC(0xd15907d9), SHC(0x77320d0d), SHC(0xf0f488d9), SHC(0x7f1cde01), + SHC(0x11899ed3), SHC(0x7ecaf9e5), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7a7d055b), SHC(0xdad7f3a2), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xc3a94590), SHC(0x8f1d343a), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x8f1d343a), SHC(0xc3a94590), SHC(0x8275a0c0), SHC(0xe70747c4), + SHC(0x809dc971), SHC(0x0c8bd35e), SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9d0dfe54), SHC(0x5133cc94), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xdad7f3a2), SHC(0x7a7d055b), SHC(0x00000000), SHC(0x7fffffff), + SHC(0x25280c5e), SHC(0x7a7d055b), SHC(0x471cece7), SHC(0x6a6d98a4), SHC(0x62f201ac), SHC(0x5133cc94)}; + + +/* Twiddle coefficients for 32x8 FFTs, generated by fft_tables.py */ +# ifdef ENABLE_HR_MODE +const Word32 RotVector_32_8[2 * (256 - 32)] = { +# else +const Word16 RotVector_32_8[2 * (256 - 32)] = { +# endif + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ff62182), SHC(0xfcdbd541), SHC(0x7fd8878e), SHC(0xf9b82684), + SHC(0x7fa736b4), SHC(0xf6956fb7), SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7f0991c4), SHC(0xf054d8d5), + SHC(0x7e9d55fc), SHC(0xed37ef91), SHC(0x7e1d93ea), SHC(0xea1debbb), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7ce3ceb2), SHC(0xe3f47d96), SHC(0x7c29fbee), SHC(0xe0e60685), SHC(0x7b5d039e), SHC(0xdddc5b3b), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x798a23b1), SHC(0xd7d946d8), SHC(0x78848414), SHC(0xd4e0cb15), + SHC(0x776c4edb), SHC(0xd1eef59e), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x7504d345), SHC(0xcc210d79), + SHC(0x73b5ebd1), SHC(0xc945dfec), SHC(0x72552c85), SHC(0xc67322ce), SHC(0x70e2cbc6), SHC(0xc3a94590), + SHC(0x6f5f02b2), SHC(0xc0e8b648), SHC(0x6dca0d14), SHC(0xbe31e19b), SHC(0x6c242960), SHC(0xbb8532b0), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x68a69e81), SHC(0xb64beacd), SHC(0x66cf8120), SHC(0xb3c0200c), + SHC(0x64e88926), SHC(0xb140175b), SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x60ec3830), SHC(0xac64d510), + SHC(0x5ed77c8a), SHC(0xaa0a5b2e), SHC(0x5cb420e0), SHC(0xa7bd22ac), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7fd8878e), SHC(0xf9b82684), SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7e9d55fc), SHC(0xed37ef91), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7c29fbee), SHC(0xe0e60685), SHC(0x7a7d055b), SHC(0xdad7f3a2), + SHC(0x78848414), SHC(0xd4e0cb15), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x73b5ebd1), SHC(0xc945dfec), + SHC(0x70e2cbc6), SHC(0xc3a94590), SHC(0x6dca0d14), SHC(0xbe31e19b), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x66cf8120), SHC(0xb3c0200c), SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x5ed77c8a), SHC(0xaa0a5b2e), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x55f5a4d2), SHC(0xa1288376), SHC(0x5133cc94), SHC(0x9d0dfe54), + SHC(0x4c3fdff4), SHC(0x99307ee0), SHC(0x471cece7), SHC(0x9592675c), SHC(0x41ce1e65), SHC(0x9235f2ec), + SHC(0x3c56ba70), SHC(0x8f1d343a), SHC(0x36ba2014), SHC(0x8c4a142f), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x2b1f34eb), SHC(0x877b7bec), SHC(0x25280c5e), SHC(0x8582faa5), SHC(0x1f19f97b), SHC(0x83d60412), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x12c8106f), SHC(0x8162aa04), SHC(0x0c8bd35e), SHC(0x809dc971), + SHC(0x0647d97c), SHC(0x80277872), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fa736b4), SHC(0xf6956fb7), + SHC(0x7e9d55fc), SHC(0xed37ef91), SHC(0x7ce3ceb2), SHC(0xe3f47d96), SHC(0x7a7d055b), SHC(0xdad7f3a2), + SHC(0x776c4edb), SHC(0xd1eef59e), SHC(0x73b5ebd1), SHC(0xc945dfec), SHC(0x6f5f02b2), SHC(0xc0e8b648), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x64e88926), SHC(0xb140175b), SHC(0x5ed77c8a), SHC(0xaa0a5b2e), + SHC(0x5842dd54), SHC(0xa34bdf20), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x49b41533), SHC(0x9759617f), + SHC(0x41ce1e65), SHC(0x9235f2ec), SHC(0x398cdd32), SHC(0x8daad37b), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x2826b928), SHC(0x8675dc4f), SHC(0x1f19f97b), SHC(0x83d60412), SHC(0x15e21445), SHC(0x81e26c16), + SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0x03242abf), SHC(0x8009de7e), SHC(0xf9b82684), SHC(0x80277872), + SHC(0xf054d8d5), SHC(0x80f66e3c), SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdddc5b3b), SHC(0x84a2fc62), + SHC(0xd4e0cb15), SHC(0x877b7bec), SHC(0xcc210d79), SHC(0x8afb2cbb), SHC(0xc3a94590), SHC(0x8f1d343a), + SHC(0xbb8532b0), SHC(0x93dbd6a0), SHC(0xb3c0200c), SHC(0x99307ee0), SHC(0xac64d510), SHC(0x9f13c7d0), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x70e2cbc6), SHC(0xc3a94590), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x471cece7), SHC(0x9592675c), SHC(0x3c56ba70), SHC(0x8f1d343a), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x25280c5e), SHC(0x8582faa5), SHC(0x18f8b83c), SHC(0x8275a0c0), + SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0x00000000), SHC(0x80000000), SHC(0xf3742ca2), SHC(0x809dc971), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdad7f3a2), SHC(0x8582faa5), SHC(0xcf043ab3), SHC(0x89be50c3), + SHC(0xc3a94590), SHC(0x8f1d343a), SHC(0xb8e31319), SHC(0x9592675c), SHC(0xaecc336c), SHC(0x9d0dfe54), + SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9d0dfe54), SHC(0xaecc336c), SHC(0x9592675c), SHC(0xb8e31319), + SHC(0x8f1d343a), SHC(0xc3a94590), SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x8582faa5), SHC(0xdad7f3a2), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x809dc971), SHC(0xf3742ca2), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7f0991c4), SHC(0xf054d8d5), SHC(0x7c29fbee), SHC(0xe0e60685), SHC(0x776c4edb), SHC(0xd1eef59e), + SHC(0x70e2cbc6), SHC(0xc3a94590), SHC(0x68a69e81), SHC(0xb64beacd), SHC(0x5ed77c8a), SHC(0xaa0a5b2e), + SHC(0x539b2af0), SHC(0x9f13c7d0), SHC(0x471cece7), SHC(0x9592675c), SHC(0x398cdd32), SHC(0x8daad37b), + SHC(0x2b1f34eb), SHC(0x877b7bec), SHC(0x1c0b826a), SHC(0x831c314e), SHC(0x0c8bd35e), SHC(0x809dc971), + SHC(0xfcdbd541), SHC(0x8009de7e), SHC(0xed37ef91), SHC(0x8162aa04), SHC(0xdddc5b3b), SHC(0x84a2fc62), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc0e8b648), SHC(0x90a0fd4e), SHC(0xb3c0200c), SHC(0x99307ee0), + SHC(0xa7bd22ac), SHC(0xa34bdf20), SHC(0x9d0dfe54), SHC(0xaecc336c), SHC(0x93dbd6a0), SHC(0xbb8532b0), + SHC(0x8c4a142f), SHC(0xc945dfec), SHC(0x8675dc4f), SHC(0xd7d946d8), SHC(0x8275a0c0), SHC(0xe70747c4), + SHC(0x8058c94c), SHC(0xf6956fb7), SHC(0x80277872), SHC(0x0647d97c), SHC(0x81e26c16), SHC(0x15e21445), + SHC(0x8582faa5), SHC(0x25280c5e), SHC(0x8afb2cbb), SHC(0x33def287), SHC(0x9235f2ec), SHC(0x41ce1e65), + SHC(0x9b1776da), SHC(0x4ebfe8a5), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e9d55fc), SHC(0xed37ef91), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x73b5ebd1), SHC(0xc945dfec), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x5ed77c8a), SHC(0xaa0a5b2e), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x41ce1e65), SHC(0x9235f2ec), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x1f19f97b), SHC(0x83d60412), SHC(0x0c8bd35e), SHC(0x809dc971), + SHC(0xf9b82684), SHC(0x80277872), SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xd4e0cb15), SHC(0x877b7bec), + SHC(0xc3a94590), SHC(0x8f1d343a), SHC(0xb3c0200c), SHC(0x99307ee0), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x99307ee0), SHC(0xb3c0200c), SHC(0x8f1d343a), SHC(0xc3a94590), SHC(0x877b7bec), SHC(0xd4e0cb15), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80277872), SHC(0xf9b82684), SHC(0x809dc971), SHC(0x0c8bd35e), + SHC(0x83d60412), SHC(0x1f19f97b), SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9235f2ec), SHC(0x41ce1e65), + SHC(0x9d0dfe54), SHC(0x5133cc94), SHC(0xaa0a5b2e), SHC(0x5ed77c8a), SHC(0xb8e31319), SHC(0x6a6d98a4), + SHC(0xc945dfec), SHC(0x73b5ebd1), SHC(0xdad7f3a2), SHC(0x7a7d055b), SHC(0xed37ef91), SHC(0x7e9d55fc), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e1d93ea), SHC(0xea1debbb), SHC(0x78848414), SHC(0xd4e0cb15), + SHC(0x6f5f02b2), SHC(0xc0e8b648), SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x539b2af0), SHC(0x9f13c7d0), + SHC(0x41ce1e65), SHC(0x9235f2ec), SHC(0x2e110a62), SHC(0x8893b125), SHC(0x18f8b83c), SHC(0x8275a0c0), + SHC(0x03242abf), SHC(0x8009de7e), SHC(0xed37ef91), SHC(0x8162aa04), SHC(0xd7d946d8), SHC(0x8675dc4f), + SHC(0xc3a94590), SHC(0x8f1d343a), SHC(0xb140175b), SHC(0x9b1776da), SHC(0xa1288376), SHC(0xaa0a5b2e), + SHC(0x93dbd6a0), SHC(0xbb8532b0), SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x831c314e), SHC(0xe3f47d96), + SHC(0x80277872), SHC(0xf9b82684), SHC(0x80f66e3c), SHC(0x0fab272b), SHC(0x8582faa5), SHC(0x25280c5e), + SHC(0x8daad37b), SHC(0x398cdd32), SHC(0x99307ee0), SHC(0x4c3fdff4), SHC(0xa7bd22ac), SHC(0x5cb420e0), + SHC(0xb8e31319), SHC(0x6a6d98a4), SHC(0xcc210d79), SHC(0x7504d345), SHC(0xe0e60685), SHC(0x7c29fbee), + SHC(0xf6956fb7), SHC(0x7fa736b4), SHC(0x0c8bd35e), SHC(0x7f62368f), SHC(0x2223a4c5), SHC(0x7b5d039e), + SHC(0x36ba2014), SHC(0x73b5ebd1), SHC(0x49b41533), SHC(0x68a69e81)}; + + +# ifdef ENABLE_HR_MODE +const Word32 RotVector_15_6[2 * (90 - 15)] = { +# else +const Word16 RotVector_15_6[2 * (90 - 15)] = { +# endif + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb02dc6), SHC(0xf7123849), SHC(0x7ec11aa5), SHC(0xee2f9369), + SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), SHC(0x7847d909), SHC(0xd438af17), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x71046d3e), SHC(0xc3e85b18), SHC(0x6c8cd70b), SHC(0xbc2b9b05), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x620dbe8b), SHC(0xadb922b7), SHC(0x5c13539b), SHC(0xa7156f3c), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x4ecdfec7), SHC(0x9b2276b0), SHC(0x4793a210), SHC(0x95e218c9), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ec11aa5), SHC(0xee2f9369), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), + SHC(0x74ef0ebc), SHC(0xcbf00dbe), SHC(0x6c8cd70b), SHC(0xbc2b9b05), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x4793a210), SHC(0x95e218c9), SHC(0x381c8bb5), SHC(0x8cf45113), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x163a1a7e), SHC(0x81f1d1ce), SHC(0x04779632), SHC(0x8013f61d), + SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xe108b40d), SHC(0x83cd5982), SHC(0xd00ce422), SHC(0x89520a1a), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7d33f0ca), SHC(0xe5632654), SHC(0x74ef0ebc), SHC(0xcbf00dbe), + SHC(0x678dde6e), SHC(0xb4c373ee), SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x40000000), SHC(0x9126145f), + SHC(0x278dde6e), SHC(0x8643c7b3), SHC(0x0d61304e), SHC(0x80b381ac), SHC(0xf29ecfb2), SHC(0x80b381ac), + SHC(0xd8722192), SHC(0x8643c7b3), SHC(0xc0000000), SHC(0x9126145f), SHC(0xaa59eda4), SHC(0xa0e0a15f), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x8b10f144), SHC(0xcbf00dbe), SHC(0x82cc0f36), SHC(0xe5632654), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7b0a9f8d), SHC(0xdcb7ea46), SHC(0x6c8cd70b), SHC(0xbc2b9b05), + SHC(0x55a6125c), SHC(0xa0e0a15f), SHC(0x381c8bb5), SHC(0x8cf45113), SHC(0x163a1a7e), SHC(0x81f1d1ce), + SHC(0xf29ecfb2), SHC(0x80b381ac), SHC(0xd00ce422), SHC(0x89520a1a), SHC(0xb1320139), SHC(0x9b2276b0), + SHC(0x98722192), SHC(0xb4c373ee), SHC(0x87b826f7), SHC(0xd438af17), SHC(0x804fd23a), SHC(0xf7123849), + SHC(0x82cc0f36), SHC(0x1a9cd9ac), SHC(0x8efb92c2), SHC(0x3c17a4e8), SHC(0xa3ecac65), SHC(0x58ea90c4), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7847d909), SHC(0xd438af17), SHC(0x620dbe8b), SHC(0xadb922b7), + SHC(0x40000000), SHC(0x9126145f), SHC(0x163a1a7e), SHC(0x81f1d1ce), SHC(0xe9c5e582), SHC(0x81f1d1ce), + SHC(0xc0000000), SHC(0x9126145f), SHC(0x9df24175), SHC(0xadb922b7), SHC(0x87b826f7), SHC(0xd438af17), + SHC(0x80000000), SHC(0x00000000), SHC(0x87b826f7), SHC(0x2bc750e9), SHC(0x9df24175), SHC(0x5246dd49), + SHC(0xc0000000), SHC(0x6ed9eba1), SHC(0xe9c5e582), SHC(0x7e0e2e32), SHC(0x163a1a7e), SHC(0x7e0e2e32)}; + +#if defined(SUBSET_SSWB) || defined(SUBSET_SWB) || defined(SUBSET_FB) +/* Twiddle coefficients for 32x12 FFTs, generated by fft_tables.py */ +# ifdef ENABLE_HR_MODE +const Word32 RotVector_32_12[2 * (384 - 32)] = { +# else +const Word16 RotVector_32_12[2 * (384 - 32)] = { +# endif + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffb9d15), SHC(0xfde7dbd9), SHC(0x7fee74a2), SHC(0xfbcfdc71), + SHC(0x7fd8878e), SHC(0xf9b82684), SHC(0x7fb9d759), SHC(0xf7a0dec9), SHC(0x7f92661d), SHC(0xf58a29f2), + SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7f294bfd), SHC(0xf15f0b74), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7e9d55fc), SHC(0xed37ef91), SHC(0x7e4a5426), SHC(0xeb263dbb), SHC(0x7deeaa7a), SHC(0xe915f9ba), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7d1d7958), SHC(0xe4fa4bf1), SHC(0x7ca80038), SHC(0xe2ef2a3e), + SHC(0x7c29fbee), SHC(0xe0e60685), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7b1474fd), SHC(0xdcda47b9), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x79dd3098), SHC(0xd8d82b7a), SHC(0x793501a9), SHC(0xd6db1254), + SHC(0x78848414), SHC(0xd4e0cb15), SHC(0x77cbc3f2), SHC(0xd2e9786e), SHC(0x770acdec), SHC(0xd0f53ce0), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x757075ac), SHC(0xcd1693f7), SHC(0x74972f92), SHC(0xcb2c6a82), + SHC(0x73b5ebd1), SHC(0xc945dfec), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x71dba9ab), SHC(0xc5842c7e), + SHC(0x70e2cbc6), SHC(0xc3a94590), SHC(0x6fe2313c), SHC(0xc1d2814f), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7fee74a2), SHC(0xfbcfdc71), SHC(0x7fb9d759), SHC(0xf7a0dec9), SHC(0x7f62368f), SHC(0xf3742ca2), + SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7e4a5426), SHC(0xeb263dbb), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7ca80038), SHC(0xe2ef2a3e), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7a7d055b), SHC(0xdad7f3a2), + SHC(0x793501a9), SHC(0xd6db1254), SHC(0x77cbc3f2), SHC(0xd2e9786e), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x74972f92), SHC(0xcb2c6a82), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x70e2cbc6), SHC(0xc3a94590), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x6cb2a837), SHC(0xbc6845ce), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x680b5c33), SHC(0xb5715eef), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x62f201ac), SHC(0xaecc336c), + SHC(0x603c496c), SHC(0xab9a8e6c), SHC(0x5d6c2f99), SHC(0xa8800c26), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x577ff3da), SHC(0xa293d067), SHC(0x54657194), SHC(0x9fc3b694), SHC(0x5133cc94), SHC(0x9d0dfe54), + SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x4a8ea111), SHC(0x97f4a3cd), SHC(0x471cece7), SHC(0x9592675c), + SHC(0x4397ba32), SHC(0x934d57c9), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fd8878e), SHC(0xf9b82684), + SHC(0x7f62368f), SHC(0xf3742ca2), SHC(0x7e9d55fc), SHC(0xed37ef91), SHC(0x7d8a5f40), SHC(0xe70747c4), + SHC(0x7c29fbee), SHC(0xe0e60685), SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x78848414), SHC(0xd4e0cb15), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x73b5ebd1), SHC(0xc945dfec), SHC(0x70e2cbc6), SHC(0xc3a94590), + SHC(0x6dca0d14), SHC(0xbe31e19b), SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x66cf8120), SHC(0xb3c0200c), + SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x5ed77c8a), SHC(0xaa0a5b2e), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x55f5a4d2), SHC(0xa1288376), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x4c3fdff4), SHC(0x99307ee0), + SHC(0x471cece7), SHC(0x9592675c), SHC(0x41ce1e65), SHC(0x9235f2ec), SHC(0x3c56ba70), SHC(0x8f1d343a), + SHC(0x36ba2014), SHC(0x8c4a142f), SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2b1f34eb), SHC(0x877b7bec), + SHC(0x25280c5e), SHC(0x8582faa5), SHC(0x1f19f97b), SHC(0x83d60412), SHC(0x18f8b83c), SHC(0x8275a0c0), + SHC(0x12c8106f), SHC(0x8162aa04), SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0x0647d97c), SHC(0x80277872), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7fb9d759), SHC(0xf7a0dec9), SHC(0x7ee7aa4c), SHC(0xef4aeaf1), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x793501a9), SHC(0xd6db1254), + SHC(0x7641af3d), SHC(0xcf043ab3), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x6ed9eba1), SHC(0xc0000000), + SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x603c496c), SHC(0xab9a8e6c), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x54657194), SHC(0x9fc3b694), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x471cece7), SHC(0x9592675c), SHC(0x40000000), SHC(0x9126145f), SHC(0x389cea72), SHC(0x8d334625), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x2924edac), SHC(0x86cafe57), SHC(0x2120fb83), SHC(0x845c8ae3), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x10b5150f), SHC(0x811855b4), SHC(0x085f2137), SHC(0x804628a7), + SHC(0x00000000), SHC(0x80000000), SHC(0xf7a0dec9), SHC(0x804628a7), SHC(0xef4aeaf1), SHC(0x811855b4), + SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd6db1254), SHC(0x86cafe57), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc763158e), SHC(0x8d334625), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7f92661d), SHC(0xf58a29f2), SHC(0x7e4a5426), SHC(0xeb263dbb), SHC(0x7c29fbee), SHC(0xe0e60685), + SHC(0x793501a9), SHC(0xd6db1254), SHC(0x757075ac), SHC(0xcd1693f7), SHC(0x70e2cbc6), SHC(0xc3a94590), + SHC(0x6b93d02e), SHC(0xbaa34bf4), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x5ed77c8a), SHC(0xaa0a5b2e), + SHC(0x577ff3da), SHC(0xa293d067), SHC(0x4f9292dc), SHC(0x9bbd4282), SHC(0x471cece7), SHC(0x9592675c), + SHC(0x3e2d7eb1), SHC(0x901dcec4), SHC(0x34d3957e), SHC(0x8b68d06e), SHC(0x2b1f34eb), SHC(0x877b7bec), + SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x16ea0646), SHC(0x82115586), SHC(0x0c8bd35e), SHC(0x809dc971), + SHC(0x02182427), SHC(0x800462eb), SHC(0xf7a0dec9), SHC(0x804628a7), SHC(0xed37ef91), SHC(0x8162aa04), + SHC(0xe2ef2a3e), SHC(0x8357ffc8), SHC(0xd8d82b7a), SHC(0x8622cf68), SHC(0xcf043ab3), SHC(0x89be50c3), + SHC(0xc5842c7e), SHC(0x8e245655), SHC(0xbc6845ce), SHC(0x934d57c9), SHC(0xb3c0200c), SHC(0x99307ee0), + SHC(0xab9a8e6c), SHC(0x9fc3b694), SHC(0xa405847e), SHC(0xa6fbbc59), SHC(0x9d0dfe54), SHC(0xaecc336c), + SHC(0x96bfea3d), SHC(0xb727b9f7), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f62368f), SHC(0xf3742ca2), + SHC(0x7d8a5f40), SHC(0xe70747c4), SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x70e2cbc6), SHC(0xc3a94590), SHC(0x6a6d98a4), SHC(0xb8e31319), SHC(0x62f201ac), SHC(0xaecc336c), + SHC(0x5a82799a), SHC(0xa57d8666), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x471cece7), SHC(0x9592675c), + SHC(0x3c56ba70), SHC(0x8f1d343a), SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x25280c5e), SHC(0x8582faa5), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0x00000000), SHC(0x80000000), + SHC(0xf3742ca2), SHC(0x809dc971), SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xdad7f3a2), SHC(0x8582faa5), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xc3a94590), SHC(0x8f1d343a), SHC(0xb8e31319), SHC(0x9592675c), + SHC(0xaecc336c), SHC(0x9d0dfe54), SHC(0xa57d8666), SHC(0xa57d8666), SHC(0x9d0dfe54), SHC(0xaecc336c), + SHC(0x9592675c), SHC(0xb8e31319), SHC(0x8f1d343a), SHC(0xc3a94590), SHC(0x89be50c3), SHC(0xcf043ab3), + SHC(0x8582faa5), SHC(0xdad7f3a2), SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x809dc971), SHC(0xf3742ca2), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7f294bfd), SHC(0xf15f0b74), SHC(0x7ca80038), SHC(0xe2ef2a3e), + SHC(0x78848414), SHC(0xd4e0cb15), SHC(0x72ccb9db), SHC(0xc763158e), SHC(0x6b93d02e), SHC(0xbaa34bf4), + SHC(0x62f201ac), SHC(0xaecc336c), SHC(0x590443a7), SHC(0xa405847e), SHC(0x4debe4fe), SHC(0x9a7365d3), + SHC(0x41ce1e65), SHC(0x9235f2ec), SHC(0x34d3957e), SHC(0x8b68d06e), SHC(0x2727d486), SHC(0x8622cf68), + SHC(0x18f8b83c), SHC(0x8275a0c0), SHC(0x0a75d60e), SHC(0x806d99e3), SHC(0xfbcfdc71), SHC(0x80118b5e), + SHC(0xed37ef91), SHC(0x8162aa04), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xd0f53ce0), SHC(0x88f53214), + SHC(0xc3a94590), SHC(0x8f1d343a), SHC(0xb727b9f7), SHC(0x96bfea3d), SHC(0xab9a8e6c), SHC(0x9fc3b694), + SHC(0xa1288376), SHC(0xaa0a5b2e), SHC(0x97f4a3cd), SHC(0xb5715eef), SHC(0x901dcec4), SHC(0xc1d2814f), + SHC(0x89be50c3), SHC(0xcf043ab3), SHC(0x84eb8b03), SHC(0xdcda47b9), SHC(0x81b5abda), SHC(0xeb263dbb), + SHC(0x80277872), SHC(0xf9b82684), SHC(0x804628a7), SHC(0x085f2137), SHC(0x82115586), SHC(0x16ea0646), + SHC(0x8582faa5), SHC(0x25280c5e), SHC(0x8a8f8a54), SHC(0x32e96c09), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7ee7aa4c), SHC(0xef4aeaf1), SHC(0x7ba3751d), SHC(0xdedf047d), SHC(0x7641af3d), SHC(0xcf043ab3), + SHC(0x6ed9eba1), SHC(0xc0000000), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x5a82799a), SHC(0xa57d8666), + SHC(0x4debe4fe), SHC(0x9a7365d3), SHC(0x40000000), SHC(0x9126145f), SHC(0x30fbc54d), SHC(0x89be50c3), + SHC(0x2120fb83), SHC(0x845c8ae3), SHC(0x10b5150f), SHC(0x811855b4), SHC(0x00000000), SHC(0x80000000), + SHC(0xef4aeaf1), SHC(0x811855b4), SHC(0xdedf047d), SHC(0x845c8ae3), SHC(0xcf043ab3), SHC(0x89be50c3), + SHC(0xc0000000), SHC(0x9126145f), SHC(0xb2141b02), SHC(0x9a7365d3), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x9a7365d3), SHC(0xb2141b02), SHC(0x9126145f), SHC(0xc0000000), SHC(0x89be50c3), SHC(0xcf043ab3), + SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x811855b4), SHC(0xef4aeaf1), SHC(0x80000000), SHC(0x00000000), + SHC(0x811855b4), SHC(0x10b5150f), SHC(0x845c8ae3), SHC(0x2120fb83), SHC(0x89be50c3), SHC(0x30fbc54d), + SHC(0x9126145f), SHC(0x40000000), SHC(0x9a7365d3), SHC(0x4debe4fe), SHC(0xa57d8666), SHC(0x5a82799a), + SHC(0xb2141b02), SHC(0x658c9a2d), SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e9d55fc), SHC(0xed37ef91), + SHC(0x7a7d055b), SHC(0xdad7f3a2), SHC(0x73b5ebd1), SHC(0xc945dfec), SHC(0x6a6d98a4), SHC(0xb8e31319), + SHC(0x5ed77c8a), SHC(0xaa0a5b2e), SHC(0x5133cc94), SHC(0x9d0dfe54), SHC(0x41ce1e65), SHC(0x9235f2ec), + SHC(0x30fbc54d), SHC(0x89be50c3), SHC(0x1f19f97b), SHC(0x83d60412), SHC(0x0c8bd35e), SHC(0x809dc971), + SHC(0xf9b82684), SHC(0x80277872), SHC(0xe70747c4), SHC(0x8275a0c0), SHC(0xd4e0cb15), SHC(0x877b7bec), + SHC(0xc3a94590), SHC(0x8f1d343a), SHC(0xb3c0200c), SHC(0x99307ee0), SHC(0xa57d8666), SHC(0xa57d8666), + SHC(0x99307ee0), SHC(0xb3c0200c), SHC(0x8f1d343a), SHC(0xc3a94590), SHC(0x877b7bec), SHC(0xd4e0cb15), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80277872), SHC(0xf9b82684), SHC(0x809dc971), SHC(0x0c8bd35e), + SHC(0x83d60412), SHC(0x1f19f97b), SHC(0x89be50c3), SHC(0x30fbc54d), SHC(0x9235f2ec), SHC(0x41ce1e65), + SHC(0x9d0dfe54), SHC(0x5133cc94), SHC(0xaa0a5b2e), SHC(0x5ed77c8a), SHC(0xb8e31319), SHC(0x6a6d98a4), + SHC(0xc945dfec), SHC(0x73b5ebd1), SHC(0xdad7f3a2), SHC(0x7a7d055b), SHC(0xed37ef91), SHC(0x7e9d55fc), + SHC(0x7fffffff), SHC(0x00000000), SHC(0x7e4a5426), SHC(0xeb263dbb), SHC(0x793501a9), SHC(0xd6db1254), + SHC(0x70e2cbc6), SHC(0xc3a94590), SHC(0x658c9a2d), SHC(0xb2141b02), SHC(0x577ff3da), SHC(0xa293d067), + SHC(0x471cece7), SHC(0x9592675c), SHC(0x34d3957e), SHC(0x8b68d06e), SHC(0x2120fb83), SHC(0x845c8ae3), + SHC(0x0c8bd35e), SHC(0x809dc971), SHC(0xf7a0dec9), SHC(0x804628a7), SHC(0xe2ef2a3e), SHC(0x8357ffc8), + SHC(0xcf043ab3), SHC(0x89be50c3), SHC(0xbc6845ce), SHC(0x934d57c9), SHC(0xab9a8e6c), SHC(0x9fc3b694), + SHC(0x9d0dfe54), SHC(0xaecc336c), SHC(0x9126145f), SHC(0xc0000000), SHC(0x88343c0e), SHC(0xd2e9786e), + SHC(0x8275a0c0), SHC(0xe70747c4), SHC(0x80118b5e), SHC(0xfbcfdc71), SHC(0x811855b4), SHC(0x10b5150f), + SHC(0x8582faa5), SHC(0x25280c5e), SHC(0x8d334625), SHC(0x389cea72), SHC(0x97f4a3cd), SHC(0x4a8ea111), + SHC(0xa57d8666), SHC(0x5a82799a), SHC(0xb5715eef), SHC(0x680b5c33), SHC(0xc763158e), SHC(0x72ccb9db), + SHC(0xdad7f3a2), SHC(0x7a7d055b), SHC(0xef4aeaf1), SHC(0x7ee7aa4c), SHC(0x0430238f), SHC(0x7fee74a2), + SHC(0x18f8b83c), SHC(0x7d8a5f40), SHC(0x2d168792), SHC(0x77cbc3f2), SHC(0x7fffffff), SHC(0x00000000), + SHC(0x7deeaa7a), SHC(0xe915f9ba), SHC(0x77cbc3f2), SHC(0xd2e9786e), SHC(0x6dca0d14), SHC(0xbe31e19b), + SHC(0x603c496c), SHC(0xab9a8e6c), SHC(0x4f9292dc), SHC(0x9bbd4282), SHC(0x3c56ba70), SHC(0x8f1d343a), + SHC(0x2727d486), SHC(0x8622cf68), SHC(0x10b5150f), SHC(0x811855b4), SHC(0xf9b82684), SHC(0x80277872), + SHC(0xe2ef2a3e), SHC(0x8357ffc8), SHC(0xcd1693f7), SHC(0x8a8f8a54), SHC(0xb8e31319), SHC(0x9592675c), + SHC(0xa6fbbc59), SHC(0xa405847e), SHC(0x97f4a3cd), SHC(0xb5715eef), SHC(0x8c4a142f), SHC(0xc945dfec), + SHC(0x845c8ae3), SHC(0xdedf047d), SHC(0x806d99e3), SHC(0xf58a29f2), SHC(0x809dc971), SHC(0x0c8bd35e), + SHC(0x84eb8b03), SHC(0x2325b847), SHC(0x8d334625), SHC(0x389cea72), SHC(0x99307ee0), SHC(0x4c3fdff4), + SHC(0xa8800c26), SHC(0x5d6c2f99), SHC(0xbaa34bf4), SHC(0x6b93d02e), SHC(0xcf043ab3), SHC(0x7641af3d), + SHC(0xe4fa4bf1), SHC(0x7d1d7958), SHC(0xfbcfdc71), SHC(0x7fee74a2), SHC(0x12c8106f), SHC(0x7e9d55fc), + SHC(0x2924edac), SHC(0x793501a9), SHC(0x3e2d7eb1), SHC(0x6fe2313c), SHC(0x5133cc94), SHC(0x62f201ac), + SHC(0x619a7dce), SHC(0x52cf758f)}; + + +# endif /* !defined(__XTENSA__) */ + + +/* Inverse square root table for operands running from 0.5 to ~1.0 + + (Word32) (0.5 + 1.0/sqrt((op)/CDKpow(2.0,31))) + + Note: First value is not rounded for accuracy reasons + + Implicit exponent is 1 + + Example: 0x5A82799A = Isqrt(0x40000000), exponent=1 +*/ +const Word32 isqrt_table[128 + 2] = { + 0x5A827999, 0x5A287E03, 0x59CF8CBC, 0x5977A0AC, 0x5920B4DF, 0x58CAC480, 0x5875CADE, 0x5821C364, 0x57CEA99D, + 0x577C7930, 0x572B2DE0, 0x56DAC38E, 0x568B3632, 0x563C81E0, 0x55EEA2C4, 0x55A19522, 0x55555555, 0x5509DFD0, + 0x54BF311A, 0x547545D0, 0x542C1AA4, 0x53E3AC5B, 0x539BF7CD, 0x5354F9E7, 0x530EAFA5, 0x52C91618, 0x52842A5F, + 0x523FE9AC, 0x51FC5140, 0x51B95E6B, 0x51770E8F, 0x51355F1A, 0x50F44D89, 0x50B3D768, 0x5073FA50, 0x5034B3E7, + 0x4FF601E0, 0x4FB7E1FA, 0x4F7A5202, 0x4F3D4FCF, 0x4F00D944, 0x4EC4EC4F, 0x4E8986EA, 0x4E4EA718, 0x4E144AE9, + 0x4DDA7073, 0x4DA115DA, 0x4D683948, 0x4D2FD8F4, 0x4CF7F31B, 0x4CC08605, 0x4C899000, 0x4C530F65, 0x4C1D0294, + 0x4BE767F5, 0x4BB23DF9, 0x4B7D8317, 0x4B4935CF, 0x4B1554A6, 0x4AE1DE2A, 0x4AAED0F0, 0x4A7C2B93, 0x4A49ECB3, + 0x4A1812FA, 0x49E69D16, 0x49B589BB, 0x4984D7A4, 0x49548592, 0x49249249, 0x48F4FC97, 0x48C5C34B, 0x4896E53D, + 0x48686148, 0x483A364D, 0x480C6332, 0x47DEE6E1, 0x47B1C049, 0x4784EE60, 0x4758701C, 0x472C447C, 0x47006A81, + 0x46D4E130, 0x46A9A794, 0x467EBCBA, 0x46541FB4, 0x4629CF98, 0x45FFCB80, 0x45D6128A, 0x45ACA3D5, 0x45837E88, + 0x455AA1CB, 0x45320CC8, 0x4509BEB0, 0x44E1B6B4, 0x44B9F40B, 0x449275ED, 0x446B3B96, 0x44444444, 0x441D8F3B, + 0x43F71BBF, 0x43D0E917, 0x43AAF68F, 0x43854374, 0x435FCF15, 0x433A98C6, 0x43159FDC, 0x42F0E3AE, 0x42CC6398, + 0x42A81EF6, 0x42841527, 0x4260458E, 0x423CAF8D, 0x4219528B, 0x41F62DF2, 0x41D3412A, 0x41B08BA2, 0x418E0CC8, + 0x416BC40D, 0x4149B0E5, 0x4127D2C3, 0x41062920, 0x40E4B374, 0x40C3713B, 0x40A261EF, 0x40818512, 0x4060DA22, + 0x404060A1, 0x40201814, 0x40000000, 0x3FE017EC, +}; + +const Word32 Log2_16_table1[16] = { + 0, 2934766, 5701737, 8319067, 10802114, 13163988, 15415967, 17567824, + 19628084, 21604229, 23502857, 25329821, 27090336, 28789065, 30430199, 32017515, +}; + +const Word16 Log2_16_table2[16] = { + 1433, 1351, 1278, 1212, 1153, 1099, 1051, 1006, 965, 927, 892, 860, 829, 801, 775, 750, +}; + +const Word32 InvLog2_16_table1[64] = { + 1073741824, 1085434106, 1097253708, 1109202018, 1121280436, 1133490379, 1145833280, 1158310587, + 1170923762, 1183674286, 1196563654, 1209593378, 1222764986, 1236080024, 1249540052, 1263146652, + 1276901417, 1290805962, 1304861917, 1319070932, 1333434672, 1347954824, 1362633090, 1377471191, + 1392470869, 1407633882, 1422962010, 1438457051, 1454120821, 1469955159, 1485961921, 1502142985, + 1518500250, 1535035634, 1551751076, 1568648537, 1585730000, 1602997467, 1620452965, 1638098541, + 1655936265, 1673968228, 1692196547, 1710623359, 1729250827, 1748081133, 1767116489, 1786359126, + 1805811301, 1825475297, 1845353420, 1865448001, 1885761398, 1906295993, 1927054196, 1948038440, + 1969251188, 1990694927, 2012372174, 2034285470, 2056437387, 2078830522, 2101467502, 2124350982, +}; + +const Word16 InvLog2_16_table2[64] = { + 11418, 11543, 11668, 11795, 11924, 12054, 12185, 12318, 12452, 12587, 12724, 12863, 13003, 13145, 13288, 13432, + 13579, 13727, 13876, 14027, 14180, 14334, 14490, 14648, 14808, 14969, 15132, 15297, 15463, 15632, 15802, 15974, + 16148, 16324, 16501, 16681, 16863, 17046, 17232, 17420, 17609, 17801, 17995, 18191, 18389, 18589, 18792, 18996, + 19203, 19412, 19624, 19837, 20053, 20272, 20492, 20716, 20941, 21169, 21400, 21633, 21868, 22106, 22347, 22590, +}; + +const UWord8 gf16_mult_table[256] = { + /* gf16_mult_table[a | (b << 4)] contains the product of a and b in GF(16) */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 0, 2, 4, 6, 8, 10, 12, 14, 3, 1, 7, 5, 11, 9, 15, 13, 0, 3, 6, 5, 12, 15, 10, 9, 11, 8, + 13, 14, 7, 4, 1, 2, 0, 4, 8, 12, 3, 7, 11, 15, 6, 2, 14, 10, 5, 1, 13, 9, 0, 5, 10, 15, 7, 2, 13, + 8, 14, 11, 4, 1, 9, 12, 3, 6, 0, 6, 12, 10, 11, 13, 7, 1, 5, 3, 9, 15, 14, 8, 2, 4, 0, 7, 14, 9, + 15, 8, 1, 6, 13, 10, 3, 4, 2, 5, 12, 11, 0, 8, 3, 11, 6, 14, 5, 13, 12, 4, 15, 7, 10, 2, 9, 1, 0, + 9, 1, 8, 2, 11, 3, 10, 4, 13, 5, 12, 6, 15, 7, 14, 0, 10, 7, 13, 14, 4, 9, 3, 15, 5, 8, 2, 1, 11, + 6, 12, 0, 11, 5, 14, 10, 1, 15, 4, 7, 12, 2, 9, 13, 6, 8, 3, 0, 12, 11, 7, 5, 9, 14, 2, 10, 6, 1, + 13, 15, 3, 4, 8, 0, 13, 9, 4, 1, 12, 8, 5, 2, 15, 11, 6, 3, 14, 10, 7, 0, 14, 15, 1, 13, 3, 2, 12, + 9, 7, 6, 8, 4, 10, 11, 5, 0, 15, 13, 2, 9, 6, 4, 11, 1, 14, 12, 3, 8, 7, 5, 10, +}; + +const UWord8 rs16_elp_deg2_table[256] = { + /* If the polynomial x^2 + ax + b has distinct non-zero roots z1 and z2 in GF(16), * + * then table entry a + 16*b contains log_g(z1) | log_g(z2) << 4, and otherwise it * + * contains 0. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 0, 0, 0, 0, + 105, 195, 0, 210, 0, 225, 0, 180, 120, 0, 0, 121, 0, 16, 0, 211, 0, 0, 181, 0, 0, 106, + 196, 226, 0, 0, 0, 214, 64, 0, 199, 0, 0, 0, 0, 0, 49, 184, 0, 154, 0, 229, 0, 227, + 182, 0, 0, 32, 0, 0, 0, 197, 0, 0, 122, 0, 212, 152, 0, 203, 0, 158, 128, 0, 0, 0, + 98, 113, 218, 0, 0, 0, 53, 0, 0, 65, 0, 0, 185, 110, 215, 80, 0, 0, 200, 0, 50, 0, + 0, 0, 0, 130, 205, 115, 0, 0, 160, 190, 145, 0, 0, 0, 0, 0, 0, 100, 0, 0, 168, 198, + 0, 183, 33, 0, 0, 48, 228, 213, 0, 0, 0, 0, 0, 0, 0, 0, 164, 0, 179, 0, 224, 104, + 0, 194, 149, 0, 0, 209, 0, 0, 0, 189, 99, 84, 0, 129, 0, 0, 0, 144, 0, 0, 234, 114, + 0, 0, 82, 0, 0, 0, 0, 217, 202, 0, 112, 52, 232, 0, 97, 0, 0, 0, 126, 0, 81, 201, + 0, 36, 216, 186, 0, 0, 0, 96, 0, 0, 0, 0, 0, 88, 0, 0, 0, 103, 0, 148, 178, 0, + 208, 193, 0, 58, 0, 0, 0, 0, 0, 161, 206, 0, 116, 0, 101, 0, 0, 56, 146, 176, 0, 0, + 147, 162, 222, 0, 132, 0, 0, 0, 0, 0, 177, 117, 192, 0, +}; + +const UWord16 rs16_elp_deg3_table[256] = { + /* If the polynomial x^3 + ax + b has distinct roots z1, z2 and z3 in GF(16), * + * then table entry a + 16*b contains z1) | z2 << 4 | z3 << 8, and otherwise it * + * contains 0. */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1889, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2977, 0, 0, 0, 0, 0, 3990, 1859, 0, + 0, 0, 0, 0, 0, 0, 3521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1874, 0, 3718, 0, 0, 0, + 0, 0, 0, 2433, 0, 0, 1619, 0, 0, 0, 0, 3495, 0, 0, 0, 0, 0, 0, 4065, 0, 0, 0, + 0, 0, 0, 3255, 0, 0, 0, 1602, 0, 3735, 0, 0, 0, 0, 3238, 801, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3510, 0, 0, 0, 0, 1345, 3975, 0, 0, 0, 0, 0, 0, 0, 0, 3778, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2947, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3476, 0, 4005, 0, 3461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3748, 0, 0, 2962, 0, 0, 0, 0, 4035, 0, 0, 4020, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3221, 0, 0, 0, 0, 0, 0, 2690, + 0, 0, 0, 3795, 0, 0, 0, 4050, 0, 0, 0, 0, 0, 3204, 3765, 0, 0, 0, 0, 0, 2707, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +#ifdef ENABLE_HR_MODE +const Word32 invSqrtTab[(128 + 2)] = { + 0x5A827999, 0x5A287E03, 0x59CF8CBC, 0x5977A0AC, 0x5920B4DF, 0x58CAC480, 0x5875CADE, 0x5821C364, 0x57CEA99D, + 0x577C7930, 0x572B2DE0, 0x56DAC38E, 0x568B3632, 0x563C81E0, 0x55EEA2C4, 0x55A19522, 0x55555555, 0x5509DFD0, + 0x54BF311A, 0x547545D0, 0x542C1AA4, 0x53E3AC5B, 0x539BF7CD, 0x5354F9E7, 0x530EAFA5, 0x52C91618, 0x52842A5F, + 0x523FE9AC, 0x51FC5140, 0x51B95E6B, 0x51770E8F, 0x51355F1A, 0x50F44D89, 0x50B3D768, 0x5073FA50, 0x5034B3E7, + 0x4FF601E0, 0x4FB7E1FA, 0x4F7A5202, 0x4F3D4FCF, 0x4F00D944, 0x4EC4EC4F, 0x4E8986EA, 0x4E4EA718, 0x4E144AE9, + 0x4DDA7073, 0x4DA115DA, 0x4D683948, 0x4D2FD8F4, 0x4CF7F31B, 0x4CC08605, 0x4C899000, 0x4C530F65, 0x4C1D0294, + 0x4BE767F5, 0x4BB23DF9, 0x4B7D8317, 0x4B4935CF, 0x4B1554A6, 0x4AE1DE2A, 0x4AAED0F0, 0x4A7C2B93, 0x4A49ECB3, + 0x4A1812FA, 0x49E69D16, 0x49B589BB, 0x4984D7A4, 0x49548592, 0x49249249, 0x48F4FC97, 0x48C5C34B, 0x4896E53D, + 0x48686148, 0x483A364D, 0x480C6332, 0x47DEE6E1, 0x47B1C049, 0x4784EE60, 0x4758701C, 0x472C447C, 0x47006A81, + 0x46D4E130, 0x46A9A794, 0x467EBCBA, 0x46541FB4, 0x4629CF98, 0x45FFCB80, 0x45D6128A, 0x45ACA3D5, 0x45837E88, + 0x455AA1CB, 0x45320CC8, 0x4509BEB0, 0x44E1B6B4, 0x44B9F40B, 0x449275ED, 0x446B3B96, 0x44444444, 0x441D8F3B, + 0x43F71BBF, 0x43D0E917, 0x43AAF68F, 0x43854374, 0x435FCF15, 0x433A98C6, 0x43159FDC, 0x42F0E3AE, 0x42CC6398, + 0x42A81EF6, 0x42841527, 0x4260458E, 0x423CAF8D, 0x4219528B, 0x41F62DF2, 0x41D3412A, 0x41B08BA2, 0x418E0CC8, + 0x416BC40D, 0x4149B0E5, 0x4127D2C3, 0x41062920, 0x40E4B374, 0x40C3713B, 0x40A261EF, 0x40818512, 0x4060DA22, + 0x404060A1, 0x40201814, 0x40000000, 0x3FE017EC /* , 0x3FC05F61 */ +}; +#endif diff --git a/lib_lc3plus/rom_basop_util.h b/lib_lc3plus/rom_basop_util.h new file mode 100644 index 000000000..6e757c339 --- /dev/null +++ b/lib_lc3plus/rom_basop_util.h @@ -0,0 +1,172 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef __BASOP_UTIL_ROM_H__ +#define __BASOP_UTIL_ROM_H__ + +#include "basop_util_lc3plus.h" +#include "functions.h" + +#define LD_INT_TAB_LEN 120 +#define INV_TABLE_SIZE 256 +#define SQRT_TABLE_SIZE 256 + +#ifndef CHEAP_NORM_SIZE +#define CHEAP_NORM_SIZE 161 +#endif + +#define MINSFTAB 7 +#define MAXSFTAB 25 + +#ifdef ENABLE_HR_MODE +#define SHC(x) ((Word32)x) +#else +#define SHC(x) WORD322WORD16((Word32)x) +#endif + +/** + * \brief Lookup-Table for binary logarithm + */ +extern const Word16 ldCoeff_lc3plus[7]; + +/** + \brief Lookup-Table for binary power algorithm +*/ +extern const UWord32 exp2_tab_long_lc3plus[32]; + +/** + \brief Lookup-Table for binary power algorithm +*/ +extern const UWord32 exp2w_tab_long_lc3plus[32]; + +/** + \brief Lookup-Table for binary power algorithm +*/ +extern const UWord32 exp2x_tab_long_lc3plus[32]; + +/** + * \brief 1/x, x=[0,1,2,3...] table + */ +#ifdef ENABLE_HR_MODE +extern const Word16 InvIntTable[74]; +#else +extern const Word16 InvIntTable[32]; +#endif + +/** + * \ brief Lookup for sine tables and windows. + */ +void BASOP_getTables( +#ifdef ENABLE_HR_MODE + const PWord32 **ptwiddle, + const PWord32 **sin_twiddle, +#else + const PWord16 **ptwiddle, + const PWord16 **sin_twiddle, +#endif + Word16 *sin_step, + Word16 length); + +extern const Word32 RealFFT20_twid[6]; +extern const Word32 RealFFT32_twid[10]; +extern const Word32 RealFFT40_twid[12]; +extern const Word32 RealFFT60_twid[17]; +extern const Word32 RealFFT64_twid[18]; +extern const Word32 RealFFT80_twid[22]; +extern const Word32 RealFFT96_twid[26]; +extern const Word32 RealFFT128_twid[34]; +extern const Word32 RealFFT192_twid[50]; +extern const Word32 RealFFT256_twid[66]; +extern const Word32 RealFFT384_twid[98]; +extern const Word32 RealFFT512_twid[130]; +extern const Word32 RealFFT768_twid[194]; + +#ifdef ENABLE_HR_MODE +extern const PWord32 SineTable480[241]; +extern const PWord32 SineTable320[161]; +extern const PWord32 SineTable960[481]; +#else +extern const PWord16 SineTable480[241]; +extern const PWord16 SineTable320[161]; +extern const PWord16 SineTable960[481]; +#endif + +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_15_6[2 * (90 - 15)]; +#else +extern const Word16 RotVector_15_6[2 * (90 - 15)]; +#endif + +extern const Word32 RotVector_32_32[2 * 20]; +extern const Word32 RotVector_40_32[2 * 28]; + +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_320[2 * (320 - 20)]; +#else +extern const Word16 RotVector_320[2 * (320 - 20)]; +#endif + +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_360[2 * (360 - 30)]; +#else +extern const Word16 RotVector_360[2 * (360 - 30)]; +#endif + +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_480[2 * (480 - 30)]; +#else +extern const Word16 RotVector_480[2 * (480 - 30)]; +#endif + +#ifdef ENABLE_HR_MODE +#ifdef CR8_G_ADD_75MS +extern const Word32 RotVector_720[2 * (720 - 30)]; +#endif +extern const Word32 RotVector_960[2 * (480 - 60)]; +#else +extern const Word16 RotVector_960[2 * (480 - 60)]; +#endif + +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_30_16[2 * (480 - 30)]; +#endif + +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_32_8[2 * (256 - 32)]; +#else +extern const Word16 RotVector_32_8[2 * (256 - 32)]; +#endif + +#if defined(SUBSET_SSWB) || defined(SUBSET_SWB) || defined(SUBSET_FB) +#ifdef ENABLE_HR_MODE +extern const Word32 RotVector_32_12[2 * (384 - 32)]; +#else +extern const Word16 RotVector_32_12[2 * (384 - 32)]; +#endif +#else +#define RotVector_32_12 NULL +#endif + +extern const Word32 isqrt_table[128 + 2]; + +extern const Word32 Log2_16_table1[16]; +extern const Word16 Log2_16_table2[16]; + +extern const Word32 InvLog2_16_table1[64]; +extern const Word16 InvLog2_16_table2[64]; + +extern const UWord8 gf16_mult_table[256]; +extern const UWord8 rs16_elp_deg2_table[256]; +extern const UWord16 rs16_elp_deg3_table[256]; + +#ifdef ENABLE_HR_MODE +extern const Word32 invSqrtTab[(128 + 2)]; +#endif + +#endif diff --git a/lib_lc3plus/scale_signal24_fx.c b/lib_lc3plus/scale_signal24_fx.c new file mode 100644 index 000000000..548788d2a --- /dev/null +++ b/lib_lc3plus/scale_signal24_fx.c @@ -0,0 +1,121 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void scale_signal24_fx(Word32 x[], /* i: time input signal */ +#ifdef ENABLE_HR_MODE + Word32 x_scaled[], +#else + Word16 x_scaled[], +#endif + Word16 *x_exp, +#ifdef ENABLE_HR_MODE + Word32 mdct_mem[], +#else + Word16 mdct_mem[], +#endif + Word16 mdct_mem_len, + Word16 resample_mem_in[], Word16 resample_mem_in_len, Word32 resample_mem_in50[], + Word16 resample_mem_out[], Word16 resample_mem_out_len, Word32 mdct_mem32[], Word16 N, + Word32 resamp_mem32[], Word16 mem_s12k8[], Word16 *resamp_scale) +{ + Word16 i; + Word16 s; + Word16 scales[6]; + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("scale_signal24_fx", sizeof(struct { + Word16 i; + Word16 s; + Word16 scales[6]; + })); +#endif + + /* Scale input for 24 bit case */ + /* assure 24 bit input */ + FOR (i = 0; i < N; i++) + { + IF (x[i] >= 0) + { + x[i] = L_and(x[i], 0x007fffff); + } + ELSE + { + x[i] = (Word32)L_or( (UWord32)x[i], 0xff800000); + } + } + + /* Find maximum exponent */ + scales[0] = sub(15 + 8, getScaleFactor32_0(x, N)); + scales[1] = sub(15 + 8, getScaleFactor32_0(mdct_mem32, mdct_mem_len)); + scales[2] = sub(15 + 8, getScaleFactor32_0(resamp_mem32, resample_mem_in_len)); + scales[3] = sub(sub(*resamp_scale, 2), getScaleFactor32_0(resample_mem_in50, 2)); + scales[4] = sub(sub(*resamp_scale, 2), getScaleFactor16_0(resample_mem_out, resample_mem_out_len)); + scales[5] = sub(sub(*resamp_scale, 2), getScaleFactor16_0(mem_s12k8, 3)); + *x_exp = 7; move16(); + FOR (i = 0; i < 6; i++) + { + *x_exp = s_max(*x_exp, scales[i]); move16(); + } + + /* Shift input buffers */ + s = sub(15 + 8, *x_exp); + FOR (i = 0; i < N; i++) + { +#ifdef ENABLE_HR_MODE + x_scaled[i] = L_shl(x[i], s); +#else + x_scaled[i] = round_fx_sat(L_shl(x[i], s)); +#endif + } + + FOR (i = 0; i < mdct_mem_len; i++) + { +#ifdef ENABLE_HR_MODE + mdct_mem[i] = L_shl(mdct_mem32[i], s); +#else + mdct_mem[i] = round_fx_sat(L_shl(mdct_mem32[i], s)); +#endif + } + + FOR (i = 0; i < resample_mem_in_len; i++) + { + resample_mem_in[i] = round_fx_sat(L_shl(resamp_mem32[i], s)); + } + + /* Adjust resampler filter and output buffers */ + s = sub(sub(*resamp_scale, 2), *x_exp); + *resamp_scale = add(*x_exp, 2); + + IF (s) + { + FOR (i = 0; i < 2; i++) + { + resample_mem_in50[i] = L_shl(resample_mem_in50[i], s); + } + FOR (i = 0; i < resample_mem_out_len; i++) + { + resample_mem_out[i] = shl(resample_mem_out[i], s); + } + + FOR (i = 0; i < 3; i++) + { + mem_s12k8[i] = shl(mem_s12k8[i], s); + } + } + /* Store part of current frame as mdct memory buffer and resampler input buffer for next frame */ + basop_memcpy(mdct_mem32, &x[N - mdct_mem_len], mdct_mem_len * sizeof(Word32)); + basop_memmove(resamp_mem32, &x[N - resample_mem_in_len], resample_mem_in_len * sizeof(Word32)); + +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + diff --git a/lib_lc3plus/setup_dec_lc3.c b/lib_lc3plus/setup_dec_lc3.c new file mode 100644 index 000000000..1d2849f56 --- /dev/null +++ b/lib_lc3plus/setup_dec_lc3.c @@ -0,0 +1,539 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include "setup_dec_lc3.h" + +/* if decoder is null only size is reported */ +/*assume 10ms for memory allocation for now */ +int alloc_decoder(LC3PLUS_Dec *decoder, int samplerate, int channels) +{ + int ch = 0; + size_t size = sizeof(LC3PLUS_Dec); + void * ltpf_mem_x = NULL, *ltpf_mem_y = NULL, *stDec_ola_mem_fx = NULL; + int max_len = DYN_MAX_LEN_EXT(samplerate); /*NB sing 80 as minimum value changes BE for NB */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word32 * plc_longterm_advc_tdc = NULL, *plc_longterm_advc_ns = NULL; + Word16 longterm_analysis_counter_max = 0, longterm_analysis_counter_max_bytebuffer = 0; +#endif + + void *q_old_res_fx = NULL; + Word16 *sharedBuf = NULL; +#if defined(ENABLE_PC) + void *q_old_d_fx = NULL; +#endif + void *plcAd = NULL, *PhECU_f0est = NULL, *PhECU_plocs = NULL; + + for (ch = 0; ch < channels; ch++) + { + DecSetup *setup = balloc(decoder, &size, sizeof(DecSetup)); +#ifdef ENABLE_HR_MODE + int q_old_len = MIN(CODEC_FS(samplerate) * 100 / 10000, MAX_BW_HR); +#else + int q_old_len = MIN(CODEC_FS(samplerate) * 100 / 10000, MAX_BW ); +#endif + int x_old_len = DYN_MAX_LEN_PCM_PLC(samplerate); /* max(pitchmax + frame ms, M+1 + pitchmax + frame/2) */ + int fs_idx = (samplerate / 10000); /* floor= integer truncation is needed here */ + + ltpf_mem_x = balloc(decoder, &size, sizeof(*setup->ltpf_mem_x) * (max_len + max_len / 40 - 2)); + ltpf_mem_y = + balloc(decoder, &size, + sizeof(*setup->ltpf_mem_y) * (max_len + CEILING(MAX_PITCH_12K8 * max_len, 128) + (max_len / 80))); + + stDec_ola_mem_fx = balloc(decoder, &size, sizeof(*setup->stDec_ola_mem_fx) * DYN_MAX_MDCT_LEN(samplerate)); + +#if defined(ENABLE_PC) + q_old_d_fx = balloc(decoder, &size, sizeof(*setup->q_old_d_fx) * q_old_len); +#endif + sharedBuf = balloc(decoder, &size, sizeof(*setup->q_old_d_fx) * q_old_len + sizeof(*setup->plcAd->x_old_tot_fx) * x_old_len); + + /* To save static RAM, a large buffer sharedBuf is used to share + * space for q_old_d_fx, x_old_tot_fx and X_sav_fx (note: + * PHASE_ECU operates only at 10ms and standard precision) + * + * If partial Concealment is active, q_old_d_fx is saved in a separate buffer + * + * The following graph provides an overview about the memory + * sharing for 10ms and normal resolution: + */ + + /* Total buffer | <--- sharedBuf ---> | */ + /* ConcealMethod 3or4 | <---q_old_d_fx---> | <-------------------- x_old_tot_fx ------------------> | */ + /* ConcealMethod 3 | <---q_old_d_fx---> | |<------- M+1+pitch_max+ (frame_len/2)----------> | */ /* first BFI-frame only? */ + /* Meth 2,prevBfi=0 | | <------- 16 ms xfp ------->| */ + /* Meth 2 | ^ X_sav_fx ptr | <-------- maintained old_tot_fx ---------> | */ /* pitchmax samples maintained */ + /* Meth 2 | <----- X_sav 16 ms ----------> | ^xfp_fx ptr | */ + /* Meth2 ,prevBfi=1 | | <-12.25(forTDC),3.75(PLC2)->| */ /*the part used by PhECU is 3.75ms */ + /* ConcealMethod 2 |<- <10ms ->| */ + int max_plocs = DYN_MAX_PLOCS(samplerate); + plcAd = balloc(decoder, &size, sizeof(*setup->plcAd)); + PhECU_f0est = balloc(decoder, &size, sizeof(*setup->plcAd->PhECU_f0est) * max_plocs); + PhECU_plocs = balloc(decoder, &size, sizeof(*setup->plcAd->PhECU_plocs) * max_plocs); +#ifdef ENABLE_HR_MODE + q_old_res_fx = balloc(decoder, &size, sizeof(*setup->q_old_res_fx) * max_len); +#else + q_old_res_fx = balloc(decoder, &size, sizeof(*setup->q_old_res_fx) * MIN(max_len, MAX_BW)); +#endif + +#ifdef CR8_A_PLC_FADEOUT_TUNING +/* longterm_analysis_counter_max = PLC_LONGTERM_ANALYSIS_MS * (100.0f / 25.0f);*/ +/* assert(longterm_analysis_counter_max == (PLC_LONGTERM_ANALYSIS_MS * (100 /25))); */ /* test integer division for compatibility */ +/* longterm_analysis_counter_max_bytebuffer = floor(longterm_analysis_counter_max / 30.0); */ +/* assert(longterm_analysis_counter_max_bytebuffer == (longterm_analysis_counter_max / 30)); */ /* test integer division for compatibility */ + +/* longterm_analysis_counter_max = (longterm_analysis_counter_max_bytebuffer+1) * 30; */ + + longterm_analysis_counter_max = plc_fadeout_param_maxlen[0]; + longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[0]; + + plc_longterm_advc_tdc = balloc(decoder, &size, sizeof(Word32) * longterm_analysis_counter_max_bytebuffer); + plc_longterm_advc_ns = balloc(decoder, &size, sizeof(Word32) * longterm_analysis_counter_max_bytebuffer); +#endif + + if (decoder) + { + decoder->channel_setup[ch] = setup; + setup->ltpf_mem_x = ltpf_mem_x; + setup->ltpf_mem_y = ltpf_mem_y; + setup->stDec_ola_mem_fx = stDec_ola_mem_fx; + setup->q_old_res_fx = q_old_res_fx; +#if defined(ENABLE_PC) + setup->q_old_d_fx = q_old_d_fx; +#else + setup->q_old_d_fx = sharedBuf; +#endif + setup->plcAd = plcAd; + } + if (decoder && plcAd) + { +#ifdef ENABLE_HR_MODE + if (fs_idx > 4) + { + fs_idx = 4; + } +#endif + + setup->plcAd->x_old_tot_fx = &sharedBuf[q_old_len]; + setup->plcAd->PhECU_f0est = PhECU_f0est; + setup->plcAd->PhECU_xfp_fx = &(setup->plcAd->x_old_tot_fx[x_old_len-LprotSzPtr[fs_idx]]); /* point to the last 16ms of the x_old_tot_fx */ + setup->plcAd->PhECU_X_sav_fx = sharedBuf; /* reuse of lprot(=num_FsByResQ0[fs_idx]) values from this point fwd, i.e beyond the end of q_old_fx */ + setup->plcAd->PhECU_plocs = PhECU_plocs; + +#ifdef CR8_A_PLC_FADEOUT_TUNING + setup->plcAd->longterm_analysis_counter_max = longterm_analysis_counter_max; + setup->plcAd->longterm_analysis_counter_max_bytebuffer = longterm_analysis_counter_max_bytebuffer; + + setup->plcAd->plc_longterm_advc_tdc = plc_longterm_advc_tdc; + setup->plcAd->plc_longterm_advc_ns = plc_longterm_advc_ns; +#endif + } + } + + return (int)size; +} + +LC3PLUS_Error FillDecSetup(LC3PLUS_Dec *decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + ) +{ + int ch = 0; + + memset(decoder, 0, lc3plus_dec_get_size(samplerate, channels, plc_mode)); + alloc_decoder(decoder, samplerate, channels); + +#ifdef ENABLE_HR_MODE + decoder->hrmode = hrmode != 0; +#endif + + decoder->fs = CODEC_FS(samplerate); + decoder->fs_out = samplerate; + decoder->fs_idx = FS2FS_IDX(decoder->fs); + decoder->channels = channels; + decoder->frame_dms = 100; + decoder->plcMeth = plc_mode; + { + decoder->BW_cutoff_bits = BW_cutoff_bits_all[decoder->fs_idx]; + } + decoder->ltpf_mem_x_len = extract_l(L_shr_pos(Mpy_32_16_lc3plus(L_max(16000, decoder->fs), 16778), 11)) - 2; + decoder->ltpf_mem_y_len = extract_l(L_shr_pos(Mpy_32_16_lc3plus(decoder->fs, 18678) - 1, 5)) + 1 + + extract_l(L_shr_pos(Mpy_32_16_lc3plus(L_max(16000, decoder->fs), 16778), 12)); + + set_dec_frame_params(decoder); + + for (ch = 0; ch < decoder->channels; ch++) + { + DecSetup *setup = decoder->channel_setup[ch]; + setup->plc_damping = 32767; + setup->ltpf_mem_scale_fac_idx = -1; + move16(); + + setup->pc_seed = 24607; + setup->ns_seed = 24607; + setup->ns_cum_alpha = 32767; + + int i = 0; + /* 0 = 0kHz 1= 8kHz, 2= 16 kHz 3= 24 , 4 = 32 5=40 6=48kHz */ +#if (PHECU_XFP_LA == 0) + Word16 oneMsTab_LA[5] = {0, 0, 0, 0, 0}; +#else +# if (PHECU_XFP_LA == 4) + Word16 oneMsTab_LA[7] = {0 /*unused*/, 2, 4, 6, 8, 10 /*unused*/, 12}; +# else + Word16 oneMsTab_LA[7] = {0 /*unused*/, 8, 16, 24, 32, 40 /*unused*/, 48}; +# endif +#endif + Word16 oneMsTab[5] = {8, 16, 24, 32, 48}; + + setup->plcAd->stab_fac = 32767; + setup->plcAd->tdc_seed = 24607; + setup->plcAd->tdc_preemph_fac = plc_preemph_fac[decoder->fs_idx]; + setup->plcAd->tdc_lpc_order = 16; + setup->plcAd->PhECU_fs_idx_fx = + mult(decoder->frame_length, + (Word16)(32768.0 / 99.0)); /* truncation needed , i.e no rounding can be applied here */ + /* idx=frame/80, 0=8kHZ, 1=16kHz, 2=24 kHz, 3=32 kHz 5=*, 4=48 */ + + setup->plcAd->max_len_pcm_plc = DYN_MAX_LEN_PCM_PLC(decoder->fs); + + if ((decoder->hrmode == 0) && (samplerate <= 48000)) + { + setup->plcAd->PhECU_frame_ms = (Word16)( + decoder->frame_dms * 0.1); /* needed in PLCUpdate and PLC main functions, adjusted in first frame */ + setup->plcAd->PhECU_seed_fx = 21845; + setup->plcAd->PhECU_LprotOrg_fx = + shl_pos(oneMsTab[setup->plcAd->PhECU_fs_idx_fx], 4); /* 16 *1ms = 1.6 *framelength */ + setup->plcAd->PhECU_Lprot_fx = setup->plcAd->PhECU_LprotOrg_fx; + setup->plcAd->PhECU_LA = oneMsTab_LA[setup->plcAd->PhECU_fs_idx_fx]; + setup->plcAd->PhECU_whr_tot_taper = sub(setup->plcAd->PhECU_Lprot_fx, decoder->frame_length); /* 3+3 ms */ + setup->plcAd->PhECU_whr_tot_flat = decoder->frame_length; /* 10 ms */ + setup->plcAd->PhECU_LDWIN_OLAP = shr_pos(decoder->frame_length, 2); /* 2.5 ms */ + setup->plcAd->max_lprot = DYN_MAX_LPROT(decoder->fs); + setup->plcAd->max_plocs = DYN_MAX_PLOCS(decoder->fs); + setup->plcAd->PhECU_margin_xfp = 0; + setup->plcAd->PhECU_L_oold_xfp_w_E_fx = LTOT_MIN_MAN; + setup->plcAd->PhECU_L_old_xfp_w_E_fx = LTOT_MIN_MAN; + + setup->plcAd->PhECU_oold_xfp_w_E_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL; + setup->plcAd->PhECU_old_xfp_w_E_exp_fx = LTOT_INIT_FLAG; + + setup->plcAd->PhECU_oold_Ltot_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL; + setup->plcAd->PhECU_old_Ltot_exp_fx = LTOT_INIT_FLAG; + + + for (i = 0; i < MAX_LGW; i++) + { + setup->plcAd->PhECU_oold_grp_shape_fx[i] = + GRP_SHAPE_INIT; /* negative value will be replaced in very first calculation */ + setup->plcAd->PhECU_old_grp_shape_fx[i] = GRP_SHAPE_INIT; + } + /* t_adv=ctrl.FRAME/2 + ctrl.PhECU.LprotOrg/2 - ctrl.PhECU.LA + LDWIN_OLAP/2; */ + i = add(add(decoder->frame_length, setup->plcAd->PhECU_LprotOrg_fx), setup->plcAd->PhECU_LDWIN_OLAP); + setup->plcAd->PhECU_t_adv = sub(shr_pos(i, 1), setup->plcAd->PhECU_LA); + + for (i = 0; i < MAX_LGW; i++) + { + setup->plcAd->PhECU_mag_chg_1st[i] = 32767; + } + setup->plcAd->PhECU_beta_mute = 16384; +#ifdef CR8_A_PLC_FADEOUT_TUNING + setup->plcAd->PhECU_nonpure_tone_flag = -1; +#endif + } + } + + lc3plus_dec_set_ep_enabled(decoder, 0); + return LC3PLUS_OK; +} + +/* set frame config params */ +void set_dec_frame_params(LC3PLUS_Dec *decoder) +{ +# ifdef CR8_G_ADD_75MS + Word16 tmp = 0; +# endif +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + Word16 n; +#endif + + decoder->frame_length = extract_l(L_shr_pos(Mpy_32_16_lc3plus(decoder->fs, 20972), 6)); /* fs * 0.01*2^6 */ + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + decoder->BW_cutoff_bits = 0; + } +#endif + + SWITCH (decoder->frame_dms) + { + case 25: + decoder->frame_length = shr_pos(decoder->frame_length, 2); + decoder->la_zeroes = LowDelayShapes_n960_la_zeroes_2_5ms[decoder->fs_idx]; + decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + decoder->bands_number = bands_number_2_5ms_HR[decoder->fs_idx]; + decoder->bands_offset = bands_offset_2_5ms_HR[decoder->fs_idx - 4]; + decoder->W_fx = LowDelayShapes_n960_HRA_2_5ms[decoder->fs_idx - 4]; + decoder->W_size = LowDelayShapes_n960_len_2_5ms[decoder->fs_idx]; + decoder->yLen = decoder->frame_length; + } + else +#endif + { + decoder->bands_number = bands_number_2_5ms[decoder->fs_idx]; + decoder->bands_offset = bands_offset_2_5ms[decoder->fs_idx]; + decoder->W_fx = LowDelayShapes_n960_2_5ms[decoder->fs_idx]; + decoder->W_size = LowDelayShapes_n960_len_2_5ms[decoder->fs_idx]; + decoder->yLen = s_min(MAX_BW >> 2, decoder->frame_length); + } + + if (decoder->fs_idx == 0) + { + int ch; + for (ch = 0; ch < decoder->channels; ch++) + { + DecSetup *setup = decoder->channel_setup[ch]; + if (setup->plcAd != NULL) + { + setup->plcAd->tdc_lpc_order = 8; + } + } + } + BREAK; + case 50: + decoder->frame_length = shr_pos(decoder->frame_length, 1); + decoder->la_zeroes = LowDelayShapes_n960_la_zeroes_5ms[decoder->fs_idx]; + decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + decoder->bands_offset = bands_offset_5ms_HR[decoder->fs_idx - 4]; + decoder->W_fx = LowDelayShapes_n960_HRA_5ms[decoder->fs_idx - 4]; + decoder->W_size = LowDelayShapes_n960_len_5ms[decoder->fs_idx]; + decoder->yLen = decoder->frame_length; + decoder->bands_number = bands_number_5ms[decoder->fs_idx]; + } + else +#endif + { + decoder->bands_offset = bands_offset_5ms[decoder->fs_idx]; + decoder->W_fx = LowDelayShapes_n960_5ms[decoder->fs_idx]; + decoder->W_size = LowDelayShapes_n960_len_5ms[decoder->fs_idx]; + decoder->yLen = s_min(MAX_BW >> 1, decoder->frame_length); + decoder->bands_number = bands_number_5ms[decoder->fs_idx]; + } + BREAK; + +#ifdef CR8_G_ADD_75MS + case 75: + tmp = shr_pos(decoder->frame_length, 2); + decoder->frame_length = add(tmp, add(tmp, tmp)); + decoder->la_zeroes = LowDelayShapes_n960_la_zeroes_7_5ms[decoder->fs_idx]; + decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); +# ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + decoder->bands_offset = bands_offset_7_5ms_HR[decoder->fs_idx - 4]; + decoder->W_fx = LowDelayShapes_n960_HRA_7_5ms[decoder->fs_idx - 4]; + decoder->W_size = LowDelayShapes_n960_len_7_5ms[decoder->fs_idx]; + decoder->yLen = decoder->frame_length; + decoder->bands_number = bands_number_7_5ms[decoder->fs_idx]; + } + else +# endif + { + decoder->bands_offset = bands_offset_7_5ms[decoder->fs_idx]; + decoder->W_fx = LowDelayShapes_n960_7_5ms[decoder->fs_idx]; + decoder->W_size = LowDelayShapes_n960_len_7_5ms[decoder->fs_idx]; + decoder->yLen = s_min((MAX_BW >> 2) * 3, decoder->frame_length); + decoder->bands_number = bands_number_7_5ms[decoder->fs_idx]; + } + BREAK; +# endif + + case 100: + decoder->la_zeroes = LowDelayShapes_n960_la_zeroes[decoder->fs_idx]; + decoder->stDec_ola_mem_fx_len = sub(decoder->frame_length, decoder->la_zeroes); + decoder->bands_number = 64; + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + decoder->bands_offset = bands_offset_HR[decoder->fs_idx - 4]; + decoder->W_fx = LowDelayShapes_n960_HRA[decoder->fs_idx - 4]; + decoder->W_size = LowDelayShapes_n960_len[decoder->fs_idx]; + decoder->yLen = decoder->frame_length; + } + else +#endif + { + decoder->W_fx = LowDelayShapes_n960[decoder->fs_idx]; + decoder->W_size = LowDelayShapes_n960_len[decoder->fs_idx]; + decoder->bands_offset = bands_offset[decoder->fs_idx]; + decoder->yLen = s_min(MAX_BW, decoder->frame_length); + } + BREAK; + } + + { + int ch; + for (ch = 0; ch < decoder->channels; ch++) + { + DecSetup *setup = decoder->channel_setup[ch]; + if (setup->plcAd != NULL) + { /*only set if plcAd was actually allocated */ +#ifdef CR8_A_PLC_FADEOUT_TUNING + setup->plcAd->longterm_analysis_counter_max = plc_fadeout_param_maxlen[(decoder->frame_dms / 25) - 1]; + setup->plcAd->longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[(decoder->frame_dms / 25) - 1]; + +#endif + setup->plcAd->PhECU_frame_ms = (Word16)( + decoder->frame_dms * + 0.1); /* needed in processPLCupdate_fx(), now set properly set in first frame /second time */ + } + } + } +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + FOR (n=0; n < PLC_FADEOUT_TYPE_1_IN_MS*10/decoder->frame_dms;n++){ + decoder->alpha_type_2_table[n] = type_2_fadeout_fx(n, decoder->frame_dms); + } +#endif +} + +LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec *decoder, int ch, Word16 nBytes) +{ + int tmp = 0, totalBits = 0; + int channel_bytes = 0; + int minBytes, maxBytes; + + DecSetup *setup = decoder->channel_setup[ch]; + channel_bytes = nBytes; + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode) + { + SWITCH (decoder->frame_dms) + { + case 25: + maxBytes = 210; + minBytes = MIN_NBYTES; + BREAK; + case 50: + maxBytes = 375; + minBytes = MIN_NBYTES; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + maxBytes = 625; + minBytes = MIN_NBYTES; + BREAK; +#endif + case 100: + maxBytes = 625; + minBytes = MIN_NBYTES; + BREAK; + default: return LC3PLUS_HRMODE_ERROR; + } + } + else +#endif + { + minBytes = MIN_NBYTES; + maxBytes = MAX_NBYTES_100; + } + + if (channel_bytes < minBytes || channel_bytes > maxBytes) + { + return LC3PLUS_NUMBYTES_ERROR; + } + + setup->targetBytes = channel_bytes; + move16(); + setup->total_bits = shl(setup->targetBytes, 3); + setup->enable_lpc_weighting = (setup->total_bits < 480); + setup->quantizedGainOff = + -(s_min(115, setup->total_bits / (10 * (decoder->fs_idx + 1))) + 105 + 5 * (decoder->fs_idx + 1)); + tmp = DEPR_i_mult(80, decoder->fs_idx); + +#ifdef ENABLE_HR_MODE + if (decoder->hrmode && decoder->fs_idx == 5) + { + setup->quantizedGainOff = MAX(setup->quantizedGainOff, -181); + } +#endif + + totalBits = setup->total_bits; + + + SWITCH (decoder->frame_dms) + { + case 25: + setup->enable_lpc_weighting = 0; + /* total_bits * 2.4 */ + totalBits = extract_l(L_shr(L_mult0(19661, setup->total_bits), 13)); + BREAK; + case 50: + setup->enable_lpc_weighting = setup->total_bits < 240; + totalBits = sub(DEPR_i_mult(setup->total_bits, 2), 160); + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + setup->enable_lpc_weighting = setup->total_bits < 360; + totalBits = L_shr(L_mult0(10923, setup->total_bits), 13); + BREAK; +# endif + case 100: + BREAK; + } + + + if (sub(totalBits, add(320, tmp)) < 0) + { + setup->ltpf_scale_fac_idx = 0; + move16(); + } + else if (sub(totalBits, add(400, tmp)) < 0) + { + setup->ltpf_scale_fac_idx = 1; + move16(); + } + else if (sub(totalBits, add(480, tmp)) < 0) + { + setup->ltpf_scale_fac_idx = 2; + move16(); + } + else if (sub(totalBits, add(560, tmp)) < 0) + { + setup->ltpf_scale_fac_idx = 3; + move16(); + } + else + { + setup->ltpf_scale_fac_idx = -1; + move16(); + } + +#ifdef ENABLE_HR_MODE + /* No LTPF in hrmode */ + if (decoder->hrmode) + { + setup->ltpf_scale_fac_idx = -1; + move16(); + } +#endif + + return LC3PLUS_OK; +} + diff --git a/lib_lc3plus/setup_dec_lc3.h b/lib_lc3plus/setup_dec_lc3.h new file mode 100644 index 000000000..5c36163d3 --- /dev/null +++ b/lib_lc3plus/setup_dec_lc3.h @@ -0,0 +1,185 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef SETUP_DEC_LC3_H +#define SETUP_DEC_LC3_H + +#include "constants.h" + +typedef struct +{ + Word16 *x_old_tot_fx; /* MAX_LEN_PCM_PLC_TOT */ + Word32 *PhECU_f0est; /* MAX_PLOCS interpolated plocs */ + Word16 *PhECU_xfp_fx; /* MAX_LPROT */ + Word16 *PhECU_X_sav_fx; /* MAX_LPROT */ + Word16 *PhECU_plocs; /* MAX_PLOCS */ + Word16 *PhECU_fg_wintaper; /* MDCT_MEM_LEN_MAX */ + Word16 *PhECU_win_pre_tda; /* MAX_WIN_PRE_TDA */ + Word32 tdc_gain_c; + Word16 stab_fac; + Word16 tdc_fract; + Word16 tdc_seed; + Word16 tdc_preemph_fac; + Word16 tdc_lpc_order; + Word16 cum_fflcAtten; + Word16 harmonicBuf_fx[MAX_PITCH] ALIGN_BUFFER_STRUCT; + Word16 harmonicBuf_Q; + Word16 synthHist_fx[M] ALIGN_BUFFER_STRUCT; + Word16 cum_fading_slow; + Word16 cum_fading_fast; + Word16 PhECU_LprotOrg_fx; /* needed to change the Prot size adaptively */ + Word16 PhECU_Lprot_fx; + Word16 PhECU_fs_idx_fx; + Word16 PhECU_frame_ms; /* needed in PLC_Update and PLCMain functons*/ + Word16 PhECU_seed_fx; + Word16 PhECU_xfp_exp_fx; + Word16 PhECU_time_offs; + Word16 PhECU_X_savQ_fx; + Word16 PhECU_num_plocs; + Word16 PhECU_f0hzLtpBinQ7; /* ltp F0 in bins if available */ + Word16 PhECU_short_flag_prev; + Word16 PhECU_whr_tot_taper; + Word16 PhECU_whr_tot_flat; + Word16 PhECU_LDWIN_OLAP; + Word16 PhECU_LA; + Word16 PhECU_t_adv; + Word16 PhECU_beta_mute; + Word16 norm_corrQ15_fx; + Word16 q_fx_old_exp; + Word16 max_len_pcm_plc; + Word16 max_lprot; + Word16 max_plocs; + + /* Word32 L_tot W_energy sum exponent */ + Word16 PhECU_oold_Ltot_exp_fx; + Word16 PhECU_old_Ltot_exp_fx; + Word32 PhECU_L_oold_xfp_w_E_fx; + Word32 PhECU_L_old_xfp_w_E_fx; + Word16 PhECU_oold_xfp_w_E_exp_fx; /* input Word16 xfp exponnet */ + Word16 PhECU_old_xfp_w_E_exp_fx; + Word16 PhECU_oold_grp_shape_fx[MAX_LGW] ALIGN_BUFFER_STRUCT; + Word16 PhECU_old_grp_shape_fx[MAX_LGW] ALIGN_BUFFER_STRUCT; + Word16 PhECU_margin_xfp; +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 PhECU_nonpure_tone_flag; /* non-pure single tone indicator state */ +#endif + Word16 PhECU_mag_chg_1st[MAX_LGW] ALIGN_BUFFER_STRUCT; + Word16 PhECU_Xavg[MAX_LGW] ALIGN_BUFFER_STRUCT; + Word16 old_scf_q[M] ALIGN_BUFFER_STRUCT; + Word16 old_old_scf_q[M] ALIGN_BUFFER_STRUCT; + Word16 tdc_A[M + 1] ALIGN_BUFFER_STRUCT; + /* for now 20 ms saved Q14 or ptr to a combined ifft win and MDCT preTDA synthesis window 16 ms */ + +#ifdef CR8_A_PLC_FADEOUT_TUNING + Word16 longterm_counter_plcTdc; +# ifndef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER + Word16 longterm_counter_plcPhaseEcu; +# endif + Word16 longterm_counter_plcNsAdv; + Word16 longterm_analysis_counter_max; /* Maximum longterm frames number */ + Word16 longterm_analysis_counter_max_bytebuffer; /* Same as above but reduced for circular bit-buffer */ + Word32 *plc_longterm_advc_tdc; + Word32 *plc_longterm_advc_ns; + UWord8 plc_fadeout_type; + Word16 overall_counter; + Word8 longterm_counter_byte_position; + Word8 longterm_counter_bit_position; +#endif +} AplcSetup; + +/* Channel state and bitrate-derived values go in this struct */ +typedef struct +{ + Word16 *ltpf_mem_x; /* LTPF_MEM_X_LEN */ + Word16 *ltpf_mem_y; /* LTPF_MEM_Y_LEN */ +#ifdef ENABLE_HR_MODE + Word32 *stDec_ola_mem_fx; /* MDCT_MEM_LEN_MAX */ +#else + Word16 *stDec_ola_mem_fx; /* MDCT_MEM_LEN_MAX */ +#endif + AplcSetup *plcAd; + Word16 * q_old_d_fx; /* MAX_BW */ + Word16 q_old_fx_exp; + Word16 ns_seed; + Word16 ns_cum_alpha; + Word16 pc_nbLostFramesInRow; + Word16 pc_seed; + Word16 *q_old_res_fx; + Word16 q_old_res_fx_exp; + Word16 prev_gg; + Word16 prev_gg_e; + Word16 prev_BW_cutoff_idx_nf; + Word16 prev_fac_ns_fx; + Word16 total_bits; + Word16 enable_lpc_weighting; + Word16 stDec_ola_mem_fx_exp; + Word16 targetBytes; + Word16 ltpf_mem_e; + Word16 ltpf_mem_pitch_int; + Word16 ltpf_mem_pitch_fr; + Word16 ltpf_mem_gain; + Word16 ltpf_mem_active; + Word16 ltpf_scale_fac_idx; + Word16 ltpf_mem_scale_fac_idx; + Word16 quantizedGainOff; + Word16 prev_bfi; + Word16 prev_prev_bfi; + Word16 concealMethod; + Word16 nbLostFramesInRow; + Word16 plc_damping; + Word16 last_size; +#ifdef CR9_N_SHORT_FADE_FOR_UNSTABLE_PITCH + Word32 rel_pitch_change; +#endif +} DecSetup; + +/* Constants and sampling rate derived values go in this struct */ +struct LC3PLUS_Dec +{ + DecSetup * channel_setup[MAX_CHANNELS]; +#ifdef ENABLE_HR_MODE + const Word32 *W_fx; +#else + const Word16 *W_fx; +#endif + const Word16 *bands_offset; + Word32 fs; /* sampling rate, 44.1 maps to 48 */ + Word32 fs_out; /* output sampling rate */ + Word16 fs_idx; /* sampling rate index */ + Word16 frame_length; /* sampling rate index */ + Word16 channels; /* number of channels */ + Word16 plcMeth; /* PLC method for all channels */ + Word16 frame_dms; /* frame length in dms (decimilliseconds, 10^-4)*/ + Word16 last_size; /* size of last frame, without error protection */ + Word16 ep_enabled; /* error protection enabled */ + Word16 error_report; /* corrected errors in last frame or -1 on error */ + + Word16 n_pccw; + Word16 be_bp_left; + Word16 be_bp_right; + Word16 n_pc; + Word16 m_fec; + Word16 epmr; + Word16 combined_channel_coding; + + Word16 yLen; + Word16 W_size; + Word16 la_zeroes; + Word16 stDec_ola_mem_fx_len; + Word16 bands_number; + Word16 ltpf_mem_x_len; + Word16 ltpf_mem_y_len; + Word16 BW_cutoff_bits; + Word16 hrmode; +#ifdef CR10_A_ATTENUATION_CURVE_SELECTOR + Word16 alpha_type_2_table[80];/* PLC_FADEOUT_TYPE_1_IN_MS*10/25 */ +#endif +}; + +#endif diff --git a/lib_lc3plus/setup_enc_lc3.c b/lib_lc3plus/setup_enc_lc3.c new file mode 100644 index 000000000..7e20912bb --- /dev/null +++ b/lib_lc3plus/setup_enc_lc3.c @@ -0,0 +1,760 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" +#include "setup_enc_lc3.h" + +/* if encoder is null only size is reported */ +int alloc_encoder(LC3PLUS_Enc *encoder, int samplerate, int channels) +{ + int ch = 0; + size_t size = sizeof(LC3PLUS_Enc); + void * mdct_mem32 = NULL, *stEnc_mdct_mem = NULL; + + for (ch = 0; ch < channels; ch++) + { + EncSetup *setup = balloc(encoder, &size, sizeof(EncSetup)); + mdct_mem32 = balloc(encoder, &size, sizeof(*setup->mdct_mem32) * DYN_MAX_MDCT_LEN(samplerate)); + stEnc_mdct_mem = balloc(encoder, &size, sizeof(*setup->stEnc_mdct_mem) * DYN_MAX_MDCT_LEN(samplerate)); + if (encoder) + { + encoder->channel_setup[ch] = setup; + setup->mdct_mem32 = mdct_mem32; + setup->stEnc_mdct_mem = stEnc_mdct_mem; + } + } + + return (int)size; +} + +LC3PLUS_Error FillEncSetup(LC3PLUS_Enc *encoder, int samplerate, int channels +#ifdef ENABLE_HR_MODE + , int hrmode +#endif + , int32_t lfe_channel_array[] + ) +{ + int ch = 0; + + memset(encoder, 0, lc3plus_enc_get_size(samplerate, channels)); + alloc_encoder(encoder, samplerate, channels); + + encoder->fs = CODEC_FS(samplerate); + encoder->fs_in = samplerate; + encoder->fs_idx = FS2FS_IDX(encoder->fs); + +# ifdef ENABLE_HR_MODE + if (encoder->fs_idx > 4) + { + encoder->fs_idx = 5; + } + encoder->hrmode = hrmode != 0; +# endif + + encoder->channels = channels; + encoder->frame_dms = 100; + encoder->envelope_bits = 38; + encoder->global_gain_bits = 8; + encoder->noise_fac_bits = 3; + encoder->r12k8_mem_in_len = extract_l(L_shr_pos(Mpy_32_16_lc3plus(encoder->fs, 20972), 9)); + encoder->r12k8_mem_out_len = 24; + encoder->epmr = LC3PLUS_EPMR_ZERO; + encoder->bw_ctrl_active = 0; + encoder->bandwidth = L_shr_pos(encoder->fs, 1); + encoder->bandwidth_preset = L_shr_pos(encoder->fs, 1); + + for (ch = 0; ch < encoder->channels; ch++) + { + encoder->channel_setup[ch]->lfe = lfe_channel_array[ch] != 0; + } + + + for (ch = 0; ch < encoder->channels; ch++) + { + encoder->channel_setup[ch]->x_exp = 15; + encoder->channel_setup[ch]->resamp_exp = 17; + } + + set_enc_frame_params(encoder); + + return lc3plus_enc_set_ep_mode(encoder, LC3PLUS_EP_OFF); /* also calls update_enc_bitrate */ +} + +/* set frame config params */ +void set_enc_frame_params(LC3PLUS_Enc *encoder) +{ +#ifdef CR8_G_ADD_75MS +# ifdef ENABLE_075_DMS_MODE + Word16 tmp; +# endif +#endif + + encoder->frame_length = extract_l(L_shr_pos(Mpy_32_16_lc3plus(encoder->fs, 20972), 6)); /* fs * 0.01*2^6 */ + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + encoder->BW_cutoff_bits = 0; + } + else +# endif + { + encoder->BW_cutoff_bits = BW_cutoff_bits_all[encoder->fs_idx]; + } + + SWITCH (encoder->frame_dms) + { + case 25: + encoder->frame_length = shr_pos(encoder->frame_length, 2); + encoder->la_zeroes = LowDelayShapes_n960_la_zeroes_2_5ms[encoder->fs_idx]; + encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); + encoder->nSubdivisions = 2; + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + (LEN_12K8 >> 2); + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + encoder->bands_number = bands_number_2_5ms_HR[encoder->fs_idx]; + encoder->bands_offset = bands_offset_2_5ms_HR[encoder->fs_idx - 4]; + encoder->W_fx = LowDelayShapes_n960_HRA_2_5ms[encoder->fs_idx - 4]; + encoder->W_size = LowDelayShapes_n960_len_2_5ms[encoder->fs_idx]; + encoder->yLen = encoder->frame_length; + } + else +# endif + { + encoder->yLen = s_min(MAX_BW >> 2, encoder->frame_length); + encoder->W_fx = LowDelayShapes_n960_2_5ms[encoder->fs_idx]; + encoder->W_size = LowDelayShapes_n960_len_2_5ms[encoder->fs_idx]; + encoder->bands_number = bands_number_2_5ms[encoder->fs_idx]; + encoder->bands_offset = bands_offset_2_5ms[encoder->fs_idx]; + encoder->near_nyquist_index = encoder->bands_number - 2; + encoder->near_nyquist_flag = 0; + } + + BREAK; + case 50: + encoder->frame_length = shr_pos(encoder->frame_length, 1); + encoder->la_zeroes = LowDelayShapes_n960_la_zeroes_5ms[encoder->fs_idx]; + encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); + encoder->nSubdivisions = 2; + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + (LEN_12K8 >> 1); + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + encoder->bands_offset = bands_offset_5ms_HR[encoder->fs_idx - 4]; + encoder->W_fx = LowDelayShapes_n960_HRA_5ms[encoder->fs_idx - 4]; + encoder->W_size = LowDelayShapes_n960_len_5ms[encoder->fs_idx]; + encoder->yLen = encoder->frame_length; + encoder->bands_number = bands_number_5ms[encoder->fs_idx]; + } + else +# endif + { + encoder->yLen = s_min(MAX_BW >> 1, encoder->frame_length); + encoder->W_fx = LowDelayShapes_n960_5ms[encoder->fs_idx]; + encoder->W_size = LowDelayShapes_n960_len_5ms[encoder->fs_idx]; + encoder->bands_number = bands_number_5ms[encoder->fs_idx]; + encoder->bands_offset = bands_offset_5ms[encoder->fs_idx]; + encoder->near_nyquist_index = encoder->bands_number - 3; + encoder->near_nyquist_flag = 0; + } + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN; + BREAK; + +#ifdef CR8_G_ADD_75MS + case 75: + tmp = shr_pos(encoder->frame_length, 2); + encoder->frame_length = add(tmp, add(tmp, tmp)); + encoder->la_zeroes = LowDelayShapes_n960_la_zeroes_7_5ms[encoder->fs_idx]; + encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); + encoder->bands_number = bands_number_7_5ms[encoder->fs_idx]; + encoder->nSubdivisions = 3; + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN; + encoder->attdec_nblocks = 3; + encoder->attdec_damping = 9830; + encoder->attdec_hangover_thresh = 1; + encoder->r12k8_mem_out_len = 44; + encoder->near_nyquist_index = encoder->bands_number - 4; + encoder->near_nyquist_flag = 0; +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + encoder->yLen = encoder->frame_length; + encoder->W_fx = LowDelayShapes_n960_HRA_7_5ms[encoder->fs_idx - 4]; + encoder->W_size = LowDelayShapes_n960_len_7_5ms[encoder->fs_idx]; + encoder->bands_number = bands_number_7_5ms[encoder->fs_idx]; + encoder->bands_offset = bands_offset_7_5ms_HR[encoder->fs_idx - 4]; + } + else +# endif + { + encoder->yLen = s_min((MAX_BW >> 2) * 3, encoder->frame_length); + encoder->W_fx = LowDelayShapes_n960_7_5ms[encoder->fs_idx]; + encoder->W_size = LowDelayShapes_n960_len_7_5ms[encoder->fs_idx]; + encoder->bands_number = bands_number_7_5ms[encoder->fs_idx]; + encoder->bands_offset = bands_offset_7_5ms[encoder->fs_idx]; + } + BREAK; +# endif + + case 100: + encoder->la_zeroes = LowDelayShapes_n960_la_zeroes[encoder->fs_idx]; + encoder->stEnc_mdct_mem_len = sub(encoder->frame_length, encoder->la_zeroes); + encoder->bands_number = 64; + encoder->nSubdivisions = 3; + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN; + encoder->attdec_nblocks = 4; + encoder->attdec_damping = 16384; + encoder->attdec_hangover_thresh = 2; + encoder->near_nyquist_index = encoder->bands_number - 2; + encoder->near_nyquist_flag = 0; + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + encoder->bands_offset = bands_offset_HR[encoder->fs_idx - 4]; + encoder->W_fx = LowDelayShapes_n960_HRA[encoder->fs_idx - 4]; + encoder->W_size = LowDelayShapes_n960_len[encoder->fs_idx]; + encoder->yLen = encoder->frame_length; + } + else +# endif + { + encoder->yLen = s_min(MAX_BW, encoder->frame_length); + encoder->W_fx = LowDelayShapes_n960[encoder->fs_idx]; + encoder->W_size = LowDelayShapes_n960_len[encoder->fs_idx]; + encoder->bands_offset = bands_offset[encoder->fs_idx]; + } + BREAK; + } +} + +/* change encoder bitrate */ +LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc *encoder, int bitrate) +{ + int ch = 0; + int totalBytes = 0, maxBR = 0, minBR = 0, max_bytes = 0; + int channel_bytes = 0; + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + switch (encoder->frame_dms) + { + case 25: + maxBR = 672000; + if (encoder->fs == 48000) + { + minBR = MIN_BR_25MS_48KHZ_HR; + } + else if (encoder->fs == 96000) + { + minBR = MIN_BR_25MS_96KHZ_HR; + } + else + { + return LC3PLUS_HRMODE_ERROR; + } + break; + case 50: + maxBR = 600000; + if (encoder->fs == 48000) + { + minBR = MIN_BR_50MS_48KHZ_HR; + } + else if (encoder->fs == 96000) + { + minBR = MIN_BR_50MS_96KHZ_HR; + } + else + { + return LC3PLUS_HRMODE_ERROR; + } + break; +# ifdef CR8_G_ADD_75MS + case 75: + maxBR = 500000; + if (encoder->fs == 48000) {minBR = MIN_BR_075DMS_48KHZ_HR;} + else if (encoder->fs == 96000) {minBR = MIN_BR_075DMS_96KHZ_HR;} + else {return LC3PLUS_HRMODE_ERROR;} + BREAK; +# endif + case 100: + maxBR = 500000; + if (encoder->fs == 48000) + { + minBR = MIN_BR_100MS_48KHZ_HR; + } + else if (encoder->fs == 96000) + { + minBR = MIN_BR_100MS_96KHZ_HR; + } + else + { + return LC3PLUS_HRMODE_ERROR; + } + break; + default: return LC3PLUS_HRMODE_ERROR; + } + } + else + { + minBR = (MIN_NBYTES << 3); + maxBR = MAX_BR; + + switch (encoder->frame_dms) + { + case 25: + minBR = MIN_BR_025DMS; + maxBR = MAX_BR; + BREAK; + case 50: + minBR = MIN_BR_050DMS; + maxBR = MAX_BR; + /* have additional limitations for 5.0ms */ + SWITCH (encoder->fs_in) + { +# ifdef SUBSET_NB + case 8000: maxBR = MAX_BR_050DMS_NB; BREAK; +# endif + default: BREAK; + } + BREAK; +# ifdef CR8_G_ADD_75MS + case 75: + minBR = MIN_BR_075DMS; + maxBR = MAX_BR_075DMS; // special value for maxBR @ 7.5ms + /* have additional limitations for 7.5ms */ + SWITCH (encoder->fs_in) + { +# ifdef SUBSET_NB + case 8000: maxBR = MAX_BR_075DMS_NB ; BREAK; +# endif +# ifdef SUBSET_WB + case 16000: maxBR = MAX_BR_075DMS_WB ; BREAK; +# endif +# ifdef SUBSET_SSWB + case 24000: maxBR = MAX_BR_075DMS_SSWB; BREAK; +# endif + default: BREAK; + } + BREAK; +# endif + case 100: + /* have additional limitations for 10ms */ + minBR = MIN_BR_100DMS; + maxBR = MAX_BR; + SWITCH (encoder->fs_in) + { +# ifdef SUBSET_NB + case 8000: maxBR = MAX_BR_100DMS_NB ; BREAK; +# endif +# ifdef SUBSET_WB + case 16000: maxBR = MAX_BR_100DMS_WB ; BREAK; +# endif +# ifdef SUBSET_SSWB + case 24000: maxBR = MAX_BR_100DMS_SSWB; BREAK; +# endif + default: maxBR = MAX_BR; BREAK; + } + BREAK; + default: return LC3PLUS_FRAMEMS_ERROR; + } + + /* 441/480 in Q31 and 1000/75 in Q23 */ + if (encoder->fs_in == 44100) + { + minBR = Mpy_32_32_lc3plus(minBR, 1973000602); + maxBR = Mpy_32_32_lc3plus(maxBR, 1973000602); + } + } +#else /* ENABLE_HR_MODE */ + minBR = (MIN_NBYTES << 3); + maxBR = MAX_BR; + + switch (encoder->frame_dms) + { + case 25: + minBR = MIN_BR_025DMS; + maxBR = MAX_BR; + BREAK; + case 50: + minBR = MIN_BR_050DMS; + maxBR = MAX_BR; + /* have additional limitations for 5.0ms */ + SWITCH (encoder->fs_in) + { +# ifdef SUBSET_NB + case 8000: maxBR = MAX_BR_050DMS_NB; BREAK; +# endif + default: BREAK; + } + BREAK; +# ifdef CR8_G_ADD_75MS + case 75: + minBR = MIN_BR_075DMS; + maxBR = MAX_BR_075DMS; // special value for maxBR @ 7.5ms + /* have additional limitations for 7.5ms */ + SWITCH (encoder->fs_in) + { +# ifdef SUBSET_NB + case 8000: maxBR = MAX_BR_075DMS_NB ; BREAK; +# endif +# ifdef SUBSET_WB + case 16000: maxBR = MAX_BR_075DMS_WB ; BREAK; +# endif +# ifdef SUBSET_SSWB + case 24000: maxBR = MAX_BR_075DMS_SSWB; BREAK; +# endif + default: BREAK; + } + BREAK; +# endif + case 100: + /* have additional limitations for 10ms */ + minBR = MIN_BR_100DMS; + maxBR = MAX_BR; + SWITCH (encoder->fs_in) + { +# ifdef SUBSET_NB + case 8000: maxBR = MAX_BR_100DMS_NB ; BREAK; +# endif +# ifdef SUBSET_WB + case 16000: maxBR = MAX_BR_100DMS_WB ; BREAK; +# endif +# ifdef SUBSET_SSWB + case 24000: maxBR = MAX_BR_100DMS_SSWB; BREAK; +# endif + default: maxBR = MAX_BR; BREAK; + } + BREAK; + default: return LC3PLUS_FRAMEMS_ERROR; + } + + /* 441/480 in Q31 and 1000/75 in Q23 */ + if (encoder->fs_in == 44100) + { + minBR = Mpy_32_32_lc3plus(minBR, 1973000602); + maxBR = Mpy_32_32_lc3plus(maxBR, 1973000602); + } +#endif /* ENABLE_HR_MODE */ + + minBR *= encoder->channels; + maxBR *= encoder->channels; + + if (bitrate < minBR || bitrate > maxBR) + { + return LC3PLUS_BITRATE_ERROR; + } + + encoder->bitrate = bitrate; + encoder->lc3_br_set = 1; + + /* move stuff to encoder->channel_setup */ + + encoder->combined_channel_coding = 0; + if (encoder->channels > 1 && encoder->epmode) + { + if (encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in) <= 160) + { + encoder->combined_channel_coding = 1; + } + } + + if (encoder->epmode > 0) + { + max_bytes = bitrate * encoder->frame_length / (8 * encoder->fs_in * encoder->channels); + + if (max_bytes < FEC_SLOT_BYTES_MIN || max_bytes > FEC_SLOT_BYTES_MAX) + { + return LC3PLUS_BITRATE_ERROR; + } + } + + if (encoder->combined_channel_coding) + { + totalBytes = fec_get_data_size(encoder->epmode, encoder->combined_channel_coding, + bitrate * (Word32)encoder->frame_length / (8 * encoder->fs_in)); + + encoder->channel_setup[0]->n_pccw = + fec_get_n_pccw(bitrate * (Word32)encoder->frame_length / (8 * encoder->fs_in), encoder->epmode, + encoder->combined_channel_coding); + + encoder->channel_setup[0]->n_pc = fec_get_n_pc(encoder->epmode, encoder->channel_setup[0]->n_pccw, + bitrate * (Word32)encoder->frame_length / (8 * encoder->fs_in)); + } + else + { + totalBytes = bitrate * (Word32)encoder->frame_length / (8 * encoder->fs_in); + } + + for (ch = 0; ch < encoder->channels; ch++) + { + EncSetup *setup = encoder->channel_setup[ch]; + channel_bytes = totalBytes / encoder->channels + (ch < (totalBytes % encoder->channels)); + + if (encoder->combined_channel_coding) + { + setup->targetBytes = channel_bytes; + } + else + { + setup->targetBytes = fec_get_data_size(encoder->epmode, encoder->combined_channel_coding, channel_bytes); + setup->n_pccw = fec_get_n_pccw(channel_bytes, encoder->epmode, encoder->combined_channel_coding); + setup->n_pc = fec_get_n_pc(encoder->epmode, setup->n_pccw, channel_bytes); + } + /* reduce bandwith to 12kHz if bitrate is low */ + if (sub(encoder->frame_dms, 100) == 0 && + ((sub(setup->targetBytes, 40) < 0 && L_sub(encoder->fs, 48000) == 0) || + (sub(setup->targetBytes, 36) < 0 && L_sub(encoder->fs, 32000) == 0))) + { + encoder->bandwidth = L_min(12000, encoder->bandwidth_preset); + } + else + { + /* channel with highest index has lowest bitrate. + For a second channel with lower targetBytes, bandwidth is overwritten */ + encoder->bandwidth = encoder->bandwidth_preset; + } + + { + Word16 tmp; + + SWITCH(encoder->frame_dms) + { + case 25: tmp = 1; BREAK; + case 50: tmp = 2; BREAK; + case 75: tmp = 3; BREAK; + default : tmp = 4; BREAK; + } + + encoder->bw_ctrl_cutoff_bin = L_mult0(Mpy_32_32_lc3plus(encoder->bandwidth, 10737419), tmp); /* bandwidth * frame_dms / 5000 */ + } + + encoder->bw_index = sub( Mpy_32_32_lc3plus(encoder->bandwidth, 536871), 1); /* (bandwidth / 4000 ) - 1 */ + switch (encoder->frame_dms) + { + case 25: max_bytes = MAX_NBYTES_025; break; + case 50: max_bytes = MAX_NBYTES_050; break; +#ifdef ENABLE_075_DMS_MODE +# ifdef CR8_G_ADD_75MS + case 75: max_bytes = MAX_NBYTES_075; BREAK; +# endif +#endif + case 100: max_bytes = MAX_NBYTES_100; break; + } +#ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + max_bytes = MAX_NBYTES_RED_HR; + } +#endif + if (setup->targetBytes < MIN_NBYTES || setup->targetBytes > max_bytes) + { + return LC3PLUS_BITRATE_ERROR; + } + + setup->total_bits = shl(setup->targetBytes, 3); + setup->targetBitsInit = + sub(setup->total_bits, + add(encoder->envelope_bits, + add(encoder->global_gain_bits, add(encoder->noise_fac_bits, encoder->BW_cutoff_bits)))); + setup->targetBitsInit = sub(setup->targetBitsInit, sub(17, norm_s(sub(encoder->yLen, 1)))); + if (setup->total_bits > 1280) + { + setup->targetBitsInit = sub(setup->targetBitsInit, 1); + } + if (setup->total_bits > 2560) + { + setup->targetBitsInit = sub(setup->targetBitsInit, 1); + } + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + setup->targetBitsInit -= 1; + } +# endif + + setup->targetBitsAri = setup->total_bits; + + SWITCH (encoder->frame_dms) + { + case 25: + /* 9830 = 2.4 * 2^12 */ + setup->ltpf_enable = + sub(extract_l(L_shr(L_mult0(9830, setup->total_bits), 12)), add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = 0; + BREAK; + case 50: + setup->ltpf_enable = sub(sub(DEPR_i_mult(setup->total_bits, 2), 160), add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = setup->total_bits < 240; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + setup->ltpf_enable = sub(L_shr(L_mult0(10923, setup->total_bits), 13), add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; + setup->enable_lpc_weighting = setup->total_bits < 360; + BREAK; +# endif + case 100: + setup->enable_lpc_weighting = setup->total_bits < 480; + setup->ltpf_enable = sub(setup->total_bits, add(560, DEPR_i_mult(80, encoder->fs_idx))) < 0; + BREAK; + } + + setup->quantizedGainOff = + -(s_min(115, setup->total_bits / (10 * (encoder->fs_idx + 1))) + 105 + 5 * (encoder->fs_idx + 1)); + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode && encoder->fs_idx == 5) + { + setup->quantizedGainOff = MAX(setup->quantizedGainOff, -181); + } +# endif + +# ifdef ENABLE_HR_MODE + if (encoder->frame_dms == 100 && + ((encoder->fs_in >= 44100 && setup->targetBytes >= 100) || + (encoder->fs_in == 32000 && setup->targetBytes >= 81)) + && setup->targetBytes < 340 + && (encoder->hrmode == 0)) +# else + if (encoder->frame_dms == 100 && + ((encoder->fs_in >= 44100 && setup->targetBytes >= 100) || + (encoder->fs_in == 32000 && setup->targetBytes >= 81)) + && setup->targetBytes < 340 + ) +# endif + { + setup->attack_handling = 1; + } + else if (encoder->frame_dms == 75 && ((encoder->fs_in >= 44100 && setup->targetBytes >= 75) || + (encoder->fs_in == 32000 && setup->targetBytes >= 61)) && setup->targetBytes < 150 +# ifdef ENABLE_HR_MODE + && encoder->hrmode == 0 +# endif + ) + { + setup->attack_handling = 1; + } + else + { + /* reset attack detector for bitrate switching */ + setup->attack_handling = 0; + setup->attdec_filter_mem[0] = 0; + setup->attdec_filter_mem[1] = 0; + setup->attdec_detected = 0; + setup->attdec_position = 0; + setup->attdec_acc_energy = 0; + setup->attdec_scaling = 0; + } + +# ifdef ENABLE_HR_MODE + if (encoder->hrmode) + { + setup->ltpf_enable = 0; + } +# endif + encoder->sns_damping = SNS_DAMPING; + +# ifdef ENABLE_HR_MODE + IF (encoder->hrmode) + { + encoder->sns_damping = SNS_DAMPING_HRMODE; + IF (encoder->fs_idx >= 4) + { + IF ((encoder->frame_dms == 100) & (setup->total_bits > 4400)) + { + encoder->sns_damping = SNS_DAMPING_HRMODE_UB_10MS; + } +#ifdef CR8_G_ADD_75MS + IF ((encoder->frame_dms == 75) & (setup->total_bits > 3300)) + { + encoder->sns_damping = SNS_DAMPING_HRMODE_UB_7_5MS; + } +#endif + IF ((encoder->frame_dms == 50) & (setup->total_bits > 2300)) + { + encoder->sns_damping = SNS_DAMPING_HRMODE_UB_5MS; + } + IF ((encoder->frame_dms == 25) & (setup->total_bits > 1150)) + { + encoder->sns_damping = SNS_DAMPING_HRMODE_UB_2_5MS; + } + } + } + + if (encoder->hrmode && encoder->fs_idx >= 4) + { + int real_rate = setup->targetBytes * 8 * 10000 / encoder->frame_dms; + setup->regBits = real_rate / 12500; + + if (encoder->fs_idx == 5) + { + if (encoder->frame_dms == 100) + { + setup->regBits += 2; + } +#ifdef CR8_G_ADD_75MS + if (encoder->frame_dms == 75) + { + setup->regBits +=1; + } +#endif + if (encoder->frame_dms == 25) + { + setup->regBits -= 6; + } + } + else + { + if (encoder->frame_dms == 25) + { + setup->regBits -= 6; + } + else if (encoder->frame_dms == 50) + { + setup->regBits += 0; + } +#ifdef CR8_G_ADD_75MS + if (encoder->frame_dms == 75) + { + setup->regBits +=2; + } +#endif + if (encoder->frame_dms == 100) + { + setup->regBits += 5; + } + } + + + if (setup->regBits < 6) + { + setup->regBits = 6; + } + if (setup->regBits > 23) + { + setup->regBits = 23; + } + } + else + { + setup->regBits = -1; + } +# endif + } + + encoder->bitrate = bitrate; + + return LC3PLUS_OK; +} + diff --git a/lib_lc3plus/setup_enc_lc3.h b/lib_lc3plus/setup_enc_lc3.h new file mode 100644 index 000000000..5e89829da --- /dev/null +++ b/lib_lc3plus/setup_enc_lc3.h @@ -0,0 +1,131 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef SETUP_ENC_LC3_H +#define SETUP_ENC_LC3_H + +#include "constants.h" + +/* Channel state and bitrate-derived values go in this struct */ +typedef struct +{ +#ifdef ENABLE_HR_MODE + Word32 *stEnc_mdct_mem; /* MDCT_MEM_LEN_MAX */ +#else + Word16 *stEnc_mdct_mem; /* MDCT_MEM_LEN_MAX */ +#endif + Word32 *mdct_mem32; /* MDCT_MEM_LEN_MAX */ + Word32 targetBitsOff; + Word16 targetBytes; + Word16 total_bits; + Word16 targetBitsInit; + Word16 targetBitsAri; + Word16 enable_lpc_weighting; + Word16 ltpf_enable; + Word16 quantizedGainOff; + Word16 tns_bits; + Word16 targetBitsQuant; + Word16 olpa_mem_s6k4_exp; + Word16 olpa_mem_pitch; +#ifdef CR9_F_PITCH_WIN_LEN_FIX + Word16 pitch_flag; +#endif + Word16 ltpf_mem_in_exp; + Word16 ltpf_mem_normcorr; + Word16 ltpf_mem_mem_normcorr; + Word16 ltpf_mem_ltpf_on; + Word16 ltpf_mem_pitch; + Word16 mem_targetBits; + Word16 mem_specBits; + Word16 x_exp; + Word16 resamp_exp; + Word16 attack_handling; /* flag to enable attack handling */ + Word16 attdec_filter_mem[2]; + Word16 attdec_detected; + Word16 attdec_position; + Word32 attdec_acc_energy; + Word16 attdec_scaling; +#ifdef ENABLE_HR_MODE + Word16 regBits; + Word32 resamp_mem32[120] ALIGN_BUFFER_STRUCT; +#else + Word32 resamp_mem32[60] ALIGN_BUFFER_STRUCT; +#endif +#ifdef ENABLE_HR_MODE + Word16 r12k8_mem_in[120] ALIGN_BUFFER_STRUCT; +#else + Word16 r12k8_mem_in[60] ALIGN_BUFFER_STRUCT; +#endif + Word32 r12k8_mem_50[2] ALIGN_BUFFER_STRUCT; +#ifdef CR8_G_ADD_75MS + Word16 r12k8_mem_out[44] ALIGN_BUFFER_STRUCT; +#else + Word16 r12k8_mem_out[24] ALIGN_BUFFER_STRUCT; +#endif + Word16 olpa_mem_s12k8[3] ALIGN_BUFFER_STRUCT; + Word16 olpa_mem_s6k4[LEN_6K4 + MAX_PITCH_6K4 + 16] ALIGN_BUFFER_STRUCT; + Word16 ltpf_mem_in[LTPF_MEMIN_LEN + LEN_12K8 + 1] ALIGN_BUFFER_STRUCT; + Word16 n_pccw; + Word16 n_pc; + + Word16 lfe; +} EncSetup; + +/* Constants and sampling rate derived values go in this struct */ +struct LC3PLUS_Enc +{ + EncSetup *channel_setup[MAX_CHANNELS]; +#ifdef ENABLE_HR_MODE + const Word32 *W_fx; +#else + const Word16 *W_fx; +#endif + const Word16 *bands_offset; + + Word32 fs; /* encoder sampling rate 44.1 -> 48 */ + Word32 fs_in; /* input sampling rate */ + Word32 bitrate; /* global bitrate */ + Word16 fs_idx; /* sampling rate index */ + Word16 frame_length; /* audio samples / frame */ + Word16 channels; /* number of channels */ + Word16 epmode; /* error protection mode */ + Word16 frame_dms; /* frame length in dms (decimilliseconds, 10^-4)*/ + Word8 lc3_br_set; /* indicate if bitrate has been set */ + + Word16 yLen; + Word16 W_size; + Word16 la_zeroes; + Word16 stEnc_mdct_mem_len; + Word16 bands_number; + Word16 nSubdivisions; + Word16 ltpf_mem_in_len; + Word16 envelope_bits; + Word16 global_gain_bits; + Word16 noise_fac_bits; + Word16 BW_cutoff_bits; + Word16 r12k8_mem_in_len; + Word16 r12k8_mem_out_len; + Word16 near_nyquist_index; + Word16 near_nyquist_flag; + + Word16 epmr; + Word16 combined_channel_coding; + Word32 bandwidth; + Word32 bandwidth_preset; + Word32 bw_ctrl_active; + Word16 bw_ctrl_cutoff_bin; + Word16 bw_index; + Word16 attdec_nblocks; + Word16 attdec_damping; + Word16 attdec_hangover_thresh; + Word16 hrmode; + Word16 sns_damping; +}; + +#endif diff --git a/lib_lc3plus/sns_compute_scf_fx.c b/lib_lc3plus/sns_compute_scf_fx.c new file mode 100644 index 000000000..d56a1a7f8 --- /dev/null +++ b/lib_lc3plus/sns_compute_scf_fx.c @@ -0,0 +1,166 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processSnsComputeScf_fx(Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 n_bands, Word16 *scf, + Word16 scf_smoothing_enabled, Word16 attdec_damping_factor, Word8 *scratchBuffer, Word16 sns_damping + ) +{ + Dyn_Mem_Deluxe_In( + Word16 i, s, s2, nf, tmp; + Word32 L_mean, L_tmp; + Word32 *d3_fx; + Word16 *d3_fx_exp; + Word16 *d4_fx; + Word16 *scf_smooth; + ); + + UNUSED(attdec_damping_factor); + + d3_fx = scratchAlign(scratchBuffer, 0); /* Size = 4 * MAX_BANDS_NUMBER = 256 bytes */ + d3_fx_exp = scratchAlign(d3_fx, sizeof(*d3_fx) * MAX_BANDS_NUMBER); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ + d4_fx = scratchAlign(d3_fx_exp, sizeof(*d3_fx_exp) * MAX_BANDS_NUMBER); /* Size = 2 * MAX_BANDS_NUMBER = 128bytes */ + scf_smooth = scratchAlign(d4_fx, sizeof(*d4_fx) * MAX_BANDS_NUMBER); /* Size = 2 * 16 */ + +/* Smoothing and Pre-emphasis */ + IF (sub(n_bands, 32) < 0) + { + L_tmp = sub(32, n_bands); + FOR (i = sub(n_bands, 1); i >= L_tmp; i--) + { + d2_fx[(i + L_tmp) * 2 + 1] = d2_fx[i]; move32(); + d2_fx[(i + L_tmp) * 2 + 0] = d2_fx[i]; move32(); + } + FOR (i = sub(L_tmp, 1); i >= 0; i--) + { + d2_fx[i * 4 + 3] = d2_fx[i]; move32(); + d2_fx[i * 4 + 2] = d2_fx[i]; move32(); + d2_fx[i * 4 + 1] = d2_fx[i]; move32(); + d2_fx[i * 4 + 0] = d2_fx[i]; move32(); + } + n_bands = 64; move16(); + } + ELSE + IF (sub(n_bands, 64) < 0) + { + L_tmp = sub(64, n_bands); + FOR (i = sub(n_bands, 1); i >= L_tmp; i--) + { + d2_fx[i + L_tmp] = d2_fx[i]; move32(); + } + FOR (i = sub(L_tmp, 1); i >= 0; i--) + { + d2_fx[i * 2 + 1] = d2_fx[i]; move32(); + d2_fx[i * 2 + 0] = d2_fx[i]; move32(); + } + n_bands = 64; move16(); + } + + L_tmp = L_add(Mpy_32_16_lc3plus(d2_fx[0], 24576), L_shr_pos(d2_fx[1], 2)); + d3_fx[0] = Mpy_32_16_lc3plus(L_tmp, lpc_pre_emphasis[fs_idx][0]); move32(); + d3_fx_exp[0] = add(d2_fx_exp, lpc_pre_emphasis_e[fs_idx][0]); move16(); + FOR (i = 1; i < n_bands - 1; i++) + { + L_tmp = L_add(L_shr_pos(d2_fx[i], 1), L_add(L_shr_pos(d2_fx[i - 1], 2), L_shr_pos(d2_fx[i + 1], 2))); + d3_fx[i] = Mpy_32_16_lc3plus(L_tmp, lpc_pre_emphasis[fs_idx][i]); move32(); + d3_fx_exp[i] = add(d2_fx_exp, lpc_pre_emphasis_e[fs_idx][i]); move16(); + } + L_tmp = L_add(Mpy_32_16_lc3plus(d2_fx[n_bands - 1], 24576), L_shr_pos(d2_fx[n_bands - 2], 2)); + d3_fx[n_bands - 1] = Mpy_32_16_lc3plus(L_tmp, lpc_pre_emphasis[fs_idx][n_bands - 1]); move32(); + d3_fx_exp[n_bands - 1] = add(d2_fx_exp, lpc_pre_emphasis_e[fs_idx][n_bands - 1]); move16(); + + /* Mean */ + s = d3_fx_exp[MAX_BANDS_NUMBER - 1]; + s2 = add(s, 6); + + L_mean = L_shr(d3_fx[0], sub(s2, d3_fx_exp[0])); + FOR (i = 1; i < MAX_BANDS_NUMBER; i++) + { + L_mean = L_add(L_mean, L_shr(d3_fx[i], sub(s2, d3_fx_exp[i]))); + } + + /* Noise floor at -40dB */ + nf = BASOP_Util_Log2_16(L_mean, s); + nf = sub(s_max(nf, -25965), 6803); + +/* Log-domain */ + FOR (i = 0; i < MAX_BANDS_NUMBER; i++) + { + d4_fx[i] = s_max(nf, BASOP_Util_Log2_16(d3_fx[i], d3_fx_exp[i])); move16(); + } + + /* Downsampling */ + L_tmp = L_mult(d4_fx[0], 8192); + L_tmp = L_mac(L_tmp, d4_fx[1], 8192); + L_tmp = L_mac(L_tmp, d4_fx[2], 8192); + L_tmp = L_mac(L_tmp, d4_fx[3], 5461); + d3_fx[0] = L_mac(L_tmp, d4_fx[4], 2731); move32(); + FOR (i = 1; i < M - 1; i++) + { + L_tmp = L_mult(d4_fx[i * 4 - 1], 2731); + L_tmp = L_mac(L_tmp, d4_fx[i * 4 + 0], 5461); + L_tmp = L_mac(L_tmp, d4_fx[i * 4 + 1], 8192); + L_tmp = L_mac(L_tmp, d4_fx[i * 4 + 2], 8192); + L_tmp = L_mac(L_tmp, d4_fx[i * 4 + 3], 5461); + d3_fx[i] = L_mac(L_tmp, d4_fx[i * 4 + 4], 2731); move32(); + } + L_tmp = L_mult(d4_fx[59], 2731); + L_tmp = L_mac(L_tmp, d4_fx[60], 5461); + L_tmp = L_mac(L_tmp, d4_fx[61], 8192); + L_tmp = L_mac(L_tmp, d4_fx[62], 8192); + d3_fx[M - 1] = L_mac(L_tmp, d4_fx[63], 8192); move32(); + +/* Remove mean and scaling */ + L_mean = L_shr_pos(d3_fx[0], 4); + FOR (i = 1; i < M; i++) + { + L_mean = L_add(L_mean, L_shr_pos(d3_fx[i], 4)); + } + + FOR (i = 0; i < M; i++) + { + scf[i] = mult_r(sns_damping, round_fx(L_shl_pos(L_sub(d3_fx[i], L_mean), 1))); + move16(); + } + + /* scale factor smoothing */ + IF (scf_smoothing_enabled) + { + scf_smooth[0] = L_shr(L_mult0(L_add(L_add(scf[0], scf[1]), scf[2]), 10923), 15); + L_mean = scf_smooth[0]; move16(); + scf_smooth[1] = L_shr(L_add(L_add(L_add(scf[0], scf[1]), scf[2]), scf[3]), 2); + L_mean = L_add(L_mean, scf_smooth[1]); + FOR (i = 2; i < M - 2; i++) + { + L_tmp = L_add(L_add(L_add(L_add(scf[i - 2], scf[i - 1]), scf[i]), scf[i + 1]), scf[i + 2]); + tmp = norm_s(L_shr(L_abs(L_tmp), 15)); + if (tmp > 0) { + tmp = sub(16, tmp); + L_tmp = L_shr(L_tmp, tmp); + } + scf_smooth[i] = L_shr(L_mult0(L_tmp, 13107), sub(16, tmp)); + L_mean = L_add(L_mean, scf_smooth[i]); + } + scf_smooth[M - 2] = L_shr(L_add(L_add(L_add(scf[M - 4], scf[M - 3]), scf[M - 2]), scf[M - 1]), 2); + L_mean = L_add(L_mean, scf_smooth[M - 2]); + scf_smooth[M - 1] = L_shr(L_mult0(L_add(L_add(scf[M - 3], scf[M - 2]), scf[M - 1]), 10923), 15); + L_mean = L_add(L_mean, scf_smooth[M - 1]); + + L_mean = L_shr(L_mean, 4); + + FOR (i = 0; i < M; i++) + { + scf[i] = mult_r(attdec_damping_factor, sub(scf_smooth[i], L_mean)); + } + } + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/sns_interpolate_scf_fx.c b/lib_lc3plus/sns_interpolate_scf_fx.c new file mode 100644 index 000000000..e71825d07 --- /dev/null +++ b/lib_lc3plus/sns_interpolate_scf_fx.c @@ -0,0 +1,154 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +void processSnsInterpolateScf_fx( +#ifdef ENABLE_HR_MODE + Word32 *scf_q, Word32 mdct_scf[], +#else + Word16 *scf_q, Word16 mdct_scf[], +#endif + Word16 mdct_scf_exp[], Word16 inv_scf, + Word16 n_bands, Word8 *scratchBuffer) +{ +#ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In( + Word32 i, tmp2; + Word32 *scf_int; + Word32 tmp; + Word32 *scf_tmp; + ); +#else + Dyn_Mem_Deluxe_In( + Word16 i, tmp2; + Word16 *scf_int; + Word16 tmp; + Word16 *scf_tmp; + ); +#endif + +#ifdef ENABLE_HR_MODE + scf_int = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ + scf_tmp = (Word32 *)scratchAlign(scf_int, 4 * MAX_BANDS_NUMBER); /* 2 * MAX_BANDS_NUMBER = 128 bytes */ +#else + scf_int = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_BANDS_NUMBER = 128 bytes */ + scf_tmp = (Word16 *)scratchAlign(scf_int, 2 * MAX_BANDS_NUMBER); /* 2 * MAX_BANDS_NUMBER = 128 bytes */ +#endif + + /* Interpolation */ + scf_int[0] = scf_q[0]; + scf_int[1] = scf_q[0]; + FOR (i = 1; i < M; i++) + { +#ifdef ENABLE_HR_MODE + tmp = L_sub(scf_q[i], scf_q[i - 1]); + tmp2 = L_shr(tmp, 2); + tmp = L_shr(tmp, 3); + scf_int[i * 4 - 2] = L_add(scf_q[i - 1], tmp); + scf_int[i * 4 - 1] = L_add(scf_int[i * 4 - 2], tmp2); + scf_int[i * 4] = L_add(scf_int[i * 4 - 1], tmp2); + scf_int[i * 4 + 1] = L_add(scf_int[i * 4], tmp2); +#else + tmp = sub(scf_q[i], scf_q[i - 1]); + tmp2 = mult_r(tmp, 8192); + tmp = mult_r(tmp, 4096); + scf_int[i * 4 - 2] = add(scf_q[i - 1], tmp); + scf_int[i * 4 - 1] = add(scf_int[i * 4 - 2], tmp2); + scf_int[i * 4] = add(scf_int[i * 4 - 1], tmp2); + scf_int[i * 4 + 1] = add(scf_int[i * 4], tmp2); +#endif + } +#ifdef ENABLE_HR_MODE + scf_int[62] = L_add(scf_int[61], tmp2); + scf_int[63] = L_add(scf_int[62], tmp2); +#else + scf_int[62] = add(scf_int[61], tmp2); + scf_int[63] = add(scf_int[62], tmp2); +#endif + + /* 8 kHz mode for 2.5 ms */ + IF (sub(n_bands, 32) < 0) + { +#ifdef ENABLE_HR_MODE + basop_memmove(scf_tmp, scf_int, 64 * sizeof(Word32)); +#else + basop_memmove(scf_tmp, scf_int, 64 * sizeof(Word16)); +#endif + tmp = sub(32, n_bands); + FOR (i = 0; i < tmp; i++) + { +#ifdef ENABLE_HR_MODE + scf_int[i] = L_add(L_shr(L_add(scf_tmp[4 * i], scf_tmp[4 * i + 1]), 2), + L_shr(L_add(scf_tmp[4 * i + 2], scf_tmp[4 * i + 3]), 2)); +#else + /* 8192 = 0.25 * 2^15 */ + scf_int[i] = add(mac_r(L_mult(scf_tmp[4 * i], 8192), scf_tmp[4 * i + 1], 8192), + mac_r(L_mult(scf_tmp[4 * i + 2], 8192), scf_tmp[4 * i + 3], 8192)); +#endif + } + + FOR (i = 0; i < n_bands - tmp; i++) + { +#ifdef ENABLE_HR_MODE + scf_int[tmp + i] = L_shr(L_add(scf_tmp[4 * tmp + 2 * i], scf_tmp[4 * tmp + 2 * i + 1]), 1); +#else + scf_int[tmp + i] = mac_r(L_mult(scf_tmp[4 * tmp + 2 * i], 16384), scf_tmp[4 * tmp + 2 * i + 1], 16384); +#endif + } + } + ELSE + /* For 5ms */ + IF (sub(n_bands, 64) < 0) + { + tmp = sub(64, n_bands); + FOR (i = 0; i < tmp; i++) + { +#ifdef ENABLE_HR_MODE + scf_int[i] = L_shr(L_add(scf_int[2 * i], scf_int[2 * i + 1]), 1); +#else + scf_int[i] = mac_r(L_mult(scf_int[2 * i], 16384), scf_int[2 * i + 1], 16384); +#endif + } + FOR (; i < n_bands; i++) + { + scf_int[i] = scf_int[tmp + i]; move16(); + } +#ifdef ENABLE_HR_MODE + move16(); // 32 bit operations have twice the complexity weight of 16 bit operations +#endif + } + + /* Inversion at encoder-side*/ + IF (inv_scf == 1) + { + FOR (i = 0; i < n_bands; i++) + { +#ifdef ENABLE_HR_MODE + scf_int[i] = L_negate(scf_int[i]); +#else + scf_int[i] = negate(scf_int[i]); +#endif + } + } + +/* Linear Domain */ + FOR (i = 0; i < n_bands; i++) + { +#ifdef ENABLE_HR_MODE + /* scf_int is in Q26, BASOP_Util_InvLog2_pos requires Q25 data */ + mdct_scf[i] = BASOP_Util_InvLog2_pos(L_shr(scf_int[i], 1), &mdct_scf_exp[i]); +#else + mdct_scf[i] = BASOP_Util_InvLog2_16(scf_int[i], &mdct_scf_exp[i]); +#endif + } + + Dyn_Mem_Deluxe_Out(); +} + diff --git a/lib_lc3plus/sns_quantize_scf_fx.c b/lib_lc3plus/sns_quantize_scf_fx.c new file mode 100644 index 000000000..991381285 --- /dev/null +++ b/lib_lc3plus/sns_quantize_scf_fx.c @@ -0,0 +1,834 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static Word16 stage1_base( /* o : idx */ + const Word16 *t, /* i : target SCFs */ +#ifdef ENABLE_HR_MODE + const Word32 *cdbk, /* i : SCFs cdbk */ +#else + const Word16 *cdbk, /* i : SCFs cdbk */ +#endif + const Word16 R /* i : number of rows in codebook */ +) +{ + Counter row; + Word16 k_ptr, idx; + Word32 L_min_mse, L_mse; + Counter col; +#ifdef ENABLE_HR_MODE + Word32 err; +#else + Word16 err; +#endif + +#ifdef DYNMEM_COUNT + Dyn_Mem_In("stage1_base", sizeof(struct { + Counter row, col; + Word16 k_ptr, idx, err; + Word32 L_min_mse, L_mse; + })); +#endif +#ifdef WMOPS + BASOP_sub_sub_start("stage1_base"); +#endif + +/* find first vector error energy for */ +/* loop probably works with saturation , but it should not occur anyway */ + L_min_mse = L_add(0, 0); /* init acc with absolute min mse sofar */ + FOR (col = 0; col < M / 2; col++) /* fixed to 8 elements */ + { +#ifdef ENABLE_HR_MODE + err = L_sub(cdbk[col], L_deposit_h(t[col])); /* cdbk max abs value is 2048 = 2.^11 , max nb col is 2^3 max + target is approx similar (2.^14/M)*2 = +/- 2048 , errmax is 4096 */ + L_min_mse = L_add(L_min_mse, Mpy_32_32_lc3plus(err, err)); +#else + err = sub(cdbk[col], t[col]); /* cdbk max abs value is 2048 = 2.^11 , max nb col is 2^3 max target is approx + similar (2.^14/M)*2 = +/- 2048 , errmax is 4096 */ + L_min_mse = L_mac0(L_min_mse, err, err); /* max L_min_mse is 8*4096*4096 =2.^(3+12+12) = 2.^27 */ +#endif + } + + idx = 0; move16(); + + k_ptr = M / 2; move16(); /* ptr init to second row */ + FOR (row = 1; row < R; row++) + { + /* loop probably works with saturation , but it should not occur anyway */ + + L_mse = L_add(L_min_mse, 0); /* init acc with min mse sofar , */ + FOR (col = 0; col < M / 2; col++) /* fixed to 8 elements */ + { +#ifdef ENABLE_HR_MODE + err = L_sub(cdbk[k_ptr++], L_deposit_h(t[col])); + L_mse = L_sub(L_mse, Mpy_32_32_lc3plus(err, err)); +#else + err = sub(cdbk[k_ptr++], t[col]); + L_mse = L_msu0(L_mse, err, + err); /* NB subtraction from best MSE error sofar in acc , saturation may not occur */ +#endif + } + + L_min_mse = L_sub(L_min_mse, L_max(L_mse, 0L)); /* ALWAYS update best MSE error sofar */ + + if (L_mse > 0L) /* if acc value still is positive a new lower error energy vector was found in this row */ + { + idx = row; move16(); /* update 1-8 bits idx */ + } + + /* this inner loop(always updating L_min_mse), (L_msu, if ) consumes AV 19, WC ~20 STL cycles , + compared to a conventional(L_mac, IF( ) ) AV 21 WC ~23 STL cycles per + loop */ + } + ASSERT(idx >= 0 && idx < R); + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + + return idx; +} + +static void first_stage_split_search( +#ifdef ENABLE_HR_MODE + const Word32 *cbk_LF, const Word32 *cbk_HF, +#else + const Word16 *cbk_LF, const Word16 *cbk_HF, +#endif + const Word16 *target, + const Word16 nbCbkEntries, Word16 *idxLF, Word16 *idxHF) +{ + /* find base index for each SCF split */ + *idxLF = stage1_base(target, cbk_LF, nbCbkEntries); + *idxHF = stage1_base((&target[M / 2]), cbk_HF, nbCbkEntries); +} + +static void processDeQuantize_stage1ScfDecStage1_fx( +#ifdef ENABLE_HR_MODE + const Word32 *cbk_LF, const Word32 *cbk_HF, +#else + const Word16 *cbk_LF, const Word16 *cbk_HF, +#endif + Word16 st1_idx0, Word16 st1_idx1, +#ifdef ENABLE_HR_MODE + Word32 *st1_vector +#else + Word16 *st1_vector +#endif + ) +{ + Counter col; + Word16 offset0, offset1; +#ifdef DYNMEM_COUNT + Dyn_Mem_In("processDeQuantize_stage1ScfDecStage1_fx", sizeof(struct { + Word16 offset0, offset1; + Counter col; + })); +#endif + + offset0 = shl_pos(st1_idx0, 3); /* mult by M/2 */ + offset1 = shl_pos(st1_idx1, 3); + FOR (col = 0; col < M / 2; col++) + { + st1_vector[col] = cbk_LF[offset0++]; move16(); + st1_vector[col + 8] = cbk_HF[offset1++]; move16(); +#ifdef ENABLE_HR_MODE + move16(); + move16(); +#endif + } +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif +} + +void downshift_w32_arr(Word32 *w32_arr, Word16 *w16_arr, Word16 shft_val, Word32 len) +{ + Word32 i; + FOR (i = 0; i < len; i++) + { + w16_arr[i] = extract_l(L_shr_pos(w32_arr[i], shft_val)); + move16(); + } + return; +} + +void round_w32tow16_arr(Word32 *w32_arr, Word16 *w16_arr,Word32 len) +{ + Word32 i; + FOR (i = 0; i < len; i++) + { + w16_arr[i] = round_fx(w32_arr[i]); + move16(); + } + return; +} + +static void processQuantize_stage1ScfEncStage1_fx(const Word16 *target_st1, +#ifdef ENABLE_HR_MODE + Word32 *st1_vector, +#else + Word16 *st1_vector, +#endif + Word16 *st1_idx0Ptr, Word16 *st1_idx1Ptr) + +{ +#ifdef WMOPS + BASOP_sub_sub_start("processQuantize_stage1ScfEncStage1_fx"); +#endif + +#ifdef ENABLE_HR_MODE + first_stage_split_search(st1SCF0_7_base5_32x8_Q27, st1SCF8_15_base5_32x8_Q27, target_st1, SCF_STAGE1_NBCDKENTRIES, + st1_idx0Ptr, st1_idx1Ptr); + + processDeQuantize_stage1ScfDecStage1_fx(st1SCF0_7_base5_32x8_Q27, st1SCF8_15_base5_32x8_Q27, *st1_idx0Ptr, + *st1_idx1Ptr, st1_vector); +#else + first_stage_split_search(st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, target_st1, SCF_STAGE1_NBCDKENTRIES, + st1_idx0Ptr, st1_idx1Ptr); + + processDeQuantize_stage1ScfDecStage1_fx(st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, *st1_idx0Ptr, + *st1_idx1Ptr, st1_vector); +#endif + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + + return; +} + +/* gain-shape MSE search in warped SCF-residual domain, synthesis in SCF resiudal domain allows for easy weighting */ + +static void pvq_enc_find_best_submode_pre_post_fx( +#ifdef ENABLE_HR_MODE + const Word32 *target_st2, /* this target is in the linearized warped domain , same as input to PVQ search */ +#else + const Word16 *target_st2, /* this target is in the linearized warped domain , same as input to PVQ search */ +#endif + const Word16 *enc_pulses_far, Word16 *enc_pulses_near, const Word16 *enc_pulsesA, const Word16 *enc_pulsesB, + Word16 *sub_mode_ptr, Word16 *i_gain_ptr, +#ifdef ENABLE_HR_MODE + Word32 *enc_adj_glob_warped_vec, +#else + Word16 *enc_adj_glob_warped_vec, +#endif + Word8 *scratchBuffer) /* Size = 18 * M */ +{ + + Counter L_section, idx; +#ifdef ENABLE_HR_MODE + const Word32 *search_en1shape[N_SCF_SHAPES_ST2]; +#else + const Word16 *search_en1shape[N_SCF_SHAPES_ST2]; +#endif + const Word16 *search_gainTab[N_SCF_SHAPES_ST2]; + Word16 search_n_gains[N_SCF_SHAPES_ST2]; + Word32 L_mse, L_mse_min, L_idx; + Word16 * pulses_far, *pulses_near, *pulsesAB, *pulsesA; +#ifdef ENABLE_HR_MODE + Word32 * target_w, *shape_far, *shape_near, *shapeAB, *shapeA; +#else + Word16 * target_w, *shape_far, *shape_near, *shapeAB, *shapeA; +#endif +#ifdef ENABLE_HR_MODE + Word32 tmp, err; +#else + Word16 tmp, err; +#endif + Counter i; + +#ifdef DYNMEM_COUNT +#ifdef ENABLE_HR_MODE + Dyn_Mem_In("pvq_enc_find_best_submode_pre_post_fx", sizeof(struct { + Counter i, L_section, idx; + Word32 *search_en1shape[N_SCF_SHAPES_ST2]; + Word16 *search_gainTab[N_SCF_SHAPES_ST2]; + Word16 search_n_gains[N_SCF_SHAPES_ST2]; + Word32 L_mse, L_mse_min, L_idx; + Word16 *pulses_far, *pulses_near, *pulsesAB, *pulsesA; + Word32 *target_w, *shape_far, *shape_near, *shapeAB, *shapeA; + Word32 tmp, err; + })); +#else + Dyn_Mem_In("pvq_enc_find_best_submode_pre_post_fx", sizeof(struct { + Counter i, L_section, idx; + Word16 *search_en1shape[N_SCF_SHAPES_ST2]; + Word16 *search_gainTab[N_SCF_SHAPES_ST2]; + Word16 search_n_gains[N_SCF_SHAPES_ST2]; + Word32 L_mse, L_mse_min, L_idx; + Word16 *pulses_far, *pulses_near, *pulsesAB, *pulsesA; + Word16 *target_w, *shape_far, *shape_near, *shapeAB, *shapeA; + Word16 tmp, err; + })); +#endif /* ENABLE_HR_MODE */ +#endif /* DYNMEM_COUNT */ + + pulses_near = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * M */ + + pulsesAB = (Word16 *)scratchAlign(pulses_near, sizeof(*pulses_near) * M); /* Size = 2 * M */ + + pulsesA = (Word16 *)scratchAlign(pulsesAB, sizeof(*pulsesAB) * M); /* Size = 2 * M */ + +#ifdef ENABLE_HR_MODE + target_w = (Word32 *)scratchAlign(pulsesA, sizeof(*pulsesA) * M); /* Size = 2 * M */ + + shape_near = (Word32 *)scratchAlign(target_w, sizeof(*target_w) * M); /* Size = 4 * M */ + + shapeAB = (Word32 *)scratchAlign(shape_near, sizeof(*shape_near) * M); /* Size = 4 * M */ + + shapeA = (Word32 *)scratchAlign(shapeAB, sizeof(*shapeAB) * M); /* Size = 4 * M */ +#else + target_w = (Word16 *)scratchAlign(pulsesA, sizeof(*pulsesA) * M); /* Size = 2 * M */ + + shape_near = (Word16 *)scratchAlign(target_w, sizeof(*target_w) * M); /* Size = 2 * M */ + + shapeAB = (Word16 *)scratchAlign(shape_near, sizeof(*shape_near) * M); /* Size = 2 * M */ + + shapeA = (Word16 *)scratchAlign(shapeAB, sizeof(*shapeAB) * M); /* Size = 2 * M */ +#endif + + pulses_far = (Word16 *)scratchAlign(shapeA, sizeof(*shapeA) * M); /* Size = 2 * M */ + +#ifdef ENABLE_HR_MODE + shape_far = (Word32 *)scratchAlign(pulses_far, sizeof(*pulses_far) * M); /* Size = 2 * M */ +#else + shape_far = (Word16 *)scratchAlign(pulses_far, sizeof(*pulses_far) * M); /* Size = 2 * M */ +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("pvq_enc_find_best_submode_pre_post_fx"); +#endif + + /* construct pulse vectors and en1 normalized shape vectors */ /* use shape Q in Q14 */ + basop_memmove(pulses_far, enc_pulses_far, M * sizeof(*pulses_far)); + basop_memmove(pulses_near, enc_pulses_near, M * sizeof(*pulses_near)); + basop_memmove(target_w, target_st2, M * sizeof(*target_w)); + + pvq_dec_en1_normQ14_fx(shape_near, pulses_near, sns_Kval[2][0], M); /* near outlier mode */ + pvq_dec_en1_normQ14_fx(shape_far, pulses_far, sns_Kval[3][0], M); /* far outlier mode */ + + /* regular mode(with a split), prepare vectors of full length M */ + basop_memmove(pulsesAB, enc_pulsesA, N_SETA * sizeof(*pulsesAB)); + basop_memmove(pulsesA, enc_pulsesA, N_SETA * sizeof(*pulsesA)); + + FOR (i = N_SETA; i < M; i++) + { + pulsesAB[i] = enc_pulsesB[sub(i, N_SETA)]; move16(); + } + + IF (M > N_SETA) + { + basop_memset(&pulsesA[N_SETA], 0, (M - N_SETA) * sizeof(*pulsesA)); + } + + pvq_dec_en1_normQ14_fx(shapeAB, pulsesAB, sns_Kval[0][0], M); + /* regular AB , b_pulses = 1 ;*/ /* OPT: combine with shapeA */ + + pvq_dec_en1_normQ14_fx(shapeA, pulsesA, sns_Kval[1][0], M); + /* regular A , b_pulses = 0 */ /* OPT: M-> N_SETA */ + + /* setup search structure */ + + /* now aligned with order of j {regular=0, regular_lf=1, outlier_near=2, outlier far=3} */ + + search_en1shape[0] = shapeAB; + search_gainTab[0] = sns_gaintabPtr[0]; + search_n_gains[0] = sns_gainSz[0]; /* assumes whole bits */ + + search_en1shape[1] = shapeA; + search_gainTab[1] = sns_gaintabPtr[1]; + search_n_gains[1] = sns_gainSz[1]; /* assumes whole bits */ + + search_en1shape[2] = shape_near; + search_gainTab[2] = sns_gaintabPtr[2]; + search_n_gains[2] = sns_gainSz[2]; /*assume whole bits */ + + search_en1shape[3] = shape_far; + search_gainTab[3] = sns_gaintabPtr[3]; + search_n_gains[3] = sns_gainSz[3]; /*assume whole bits */ + + /* start actual search loop */ + + /* basic raw MSE loop, */ + L_mse_min = INT32_MAX; move32(); + L_idx = L_deposit_l(-1); /* section in low 2 bits* gain idx above */ + + FOR (L_section = 0; L_section < N_SCF_SHAPES_ST2; L_section++) + { + /* raw MSE over gain and shape */ + FOR (idx = 0; idx < search_n_gains[L_section]; idx++) + { + /* MSE ( proc_target_local[i]-adjGain[i]*en1Shape[i] ) */ + + L_mse = L_deposit_l(0); + FOR (i = 0; i < M; i++) + { +#ifdef ENABLE_HR_MODE + tmp = Mpy_32_16_lc3plus(search_en1shape[L_section][i], search_gainTab[L_section][idx]); /* Q30 + 14 - 15 = Q29 */ + err = L_sub(target_w[i], tmp); /* both in Q29 */ + L_mse = L_add(L_mse, L_shr_pos(Mpy_32_32_lc3plus(err, err), 1)); /* Q29+29-31 = Q27 */ +#else + tmp = mult_r(search_gainTab[L_section][idx], search_en1shape[L_section][i]); /* Q15+14+1-16= Q14 */ + err = sub(target_w[i], tmp); /* both in Q14 */ + L_mse = L_mac0(L_mse, err, err); /* Q14+14 = Q28 */ +#endif /* Q14+14 = Q28 */ + } + + IF (L_sub(L_mse, L_mse_min) < 0) /* OPT: always update L_mse_min) */ + { + L_mse_min = L_mse; move32(); + L_idx = L_mac0(L_section, idx, 1 << 2); /* save both section and gain idx */ + } + } /* gains */ + } /*submodes*/ + + L_section = L_and(0x3L, L_idx); /* section was stored in two lowest bits */ + ASSERT(L_section >= 0 && L_section <= 3); + *i_gain_ptr = extract_l(L_shr_pos(L_idx, 2)); /*1,2,3 bit gain */ + ASSERT(*i_gain_ptr >= 0 && *i_gain_ptr <= 7); + + /* returns a scaled and transformed vector, ___EXACTLY__ as a decoder would scale it */ + ASSERT(enc_adj_glob_warped_vec != NULL); + { + /* warp/rotate search result to SCF residual domain */ +#ifdef ENABLE_HR_MODE + idct32_32_fx(search_en1shape[L_section], target_w); +#else + idct16_fx(search_en1shape[L_section], target_w); /* fwd synthesis warping */ +#endif + /* actual synthesis gain scaling in SCF-residual domain, for easy weighting analysis */ + pvq_dec_scale_vec_fx(target_w, search_gainTab[L_section][*i_gain_ptr], enc_adj_glob_warped_vec); + } + + *sub_mode_ptr = extract_l(L_section); + move16(); /* 0,1,2,3 */ + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + return; +} + +static void processQuantize_stage2ScfEncStage2_fx( +#ifdef ENABLE_HR_MODE + const Word32 *target_st2, Word32 *st2_vector, +#else + const Word16 *target_st2, Word16 *st2_vector, +#endif + Word32 *L_prm_idx, + Word16 submodes, Word8 *scratchBuffer) /* Size = 26 * M + 48 */ +{ /*func */ +#ifdef ENABLE_HR_MODE + Word32 *proc_target; +#else + Word16 *proc_target; +#endif + + Word16 *enc_pulses_far, *enc_pulses_near, *enc_pulsesA, *enc_pulsesB; + + Word16 *pulses_fin, *pulses_proj; + Word32 L_tmp; + + Word8 *buffer_pvq_enc_find_best_submode_pre_post_fx; + + PvqEntry_fx enc_PVQ_OA, enc_PVQ_B; + Word16 submode, i_gain, submodeMSB, submodeLSB; + Word32 * L_search_corr, *L_search_en; +#ifdef ENABLE_HR_MODE + Word16 * proc_target_lp; +#endif + +#ifdef DYNMEM_COUNT +#ifdef ENABLE_HR_MODE + Dyn_Mem_In("processQuantize_stage2ScfEncStage2_fx", sizeof(struct { + Word32 *proc_target; + Word16 *enc_pulses_far, *enc_pulses_near, *enc_pulsesA, *enc_pulsesB; + Word16 *pulses_fin, *pulses_proj; + Word32 L_tmp; + Word8 *buffer_pvq_enc_find_best_submode_pre_post_fx; + PvqEntry_fx enc_PVQ_OA, enc_PVQ_B; + Word16 submode, i_gain, submodeMSB, submodeLSB; + Word32 * L_search_corr, *L_search_en; + Word16 * proc_target_lp; + })); +#else + Dyn_Mem_In("processQuantize_stage2ScfEncStage2_fx", sizeof(struct { + Word16 *proc_target; + Word16 *enc_pulses_far, *enc_pulses_near, *enc_pulsesA, *enc_pulsesB; + Word16 *pulses_fin, *pulses_proj; + Word32 L_tmp; + Word8 *buffer_pvq_enc_find_best_submode_pre_post_fx; + PvqEntry_fx enc_PVQ_OA, enc_PVQ_B; + Word16 submode, i_gain, submodeMSB, submodeLSB; + Word32 * L_search_corr, *L_search_en; + })); +#endif /* ENABLE_HR_MODE */ +#endif /* DYNMEM_COUNT */ + +#ifdef ENABLE_HR_MODE + buffer_pvq_enc_find_best_submode_pre_post_fx = (Word8 *) scratchAlign(scratchBuffer, 0); + proc_target = (Word32 *) scratchAlign(buffer_pvq_enc_find_best_submode_pre_post_fx, sizeof(*buffer_pvq_enc_find_best_submode_pre_post_fx) * 28 * M); +#else + buffer_pvq_enc_find_best_submode_pre_post_fx = scratchAlign(scratchBuffer, 0); /* Size = 18 * M */ + proc_target = + (Word16 *)scratchAlign(buffer_pvq_enc_find_best_submode_pre_post_fx, + sizeof(*buffer_pvq_enc_find_best_submode_pre_post_fx) * 18 * M); /* Size = 2 * M */ +#endif + + enc_pulses_near = (Word16 *)scratchAlign(proc_target, sizeof(*proc_target) * M); /* Size = 2 * M */ + enc_pulsesA = (Word16 *)scratchAlign(enc_pulses_near, sizeof(*enc_pulses_near) * M); /* Size = 2 * N_SETA */ + enc_pulsesB = (Word16 *)scratchAlign(enc_pulsesA, sizeof(*enc_pulsesA) * N_SETA); /* Size = 2 * N_SETB */ + pulses_fin = (Word16 *)scratchAlign(enc_pulsesB, sizeof(*enc_pulsesB) * N_SETB); /* Size = 2 * N_SCF_SHAPES_ST2 */ + pulses_proj = + (Word16 *)scratchAlign(pulses_fin, sizeof(*pulses_fin) * N_SCF_SHAPES_ST2); /* Size = 2 * N_SCF_SHAPES_ST2 */ + L_search_corr = + (Word32 *)scratchAlign(pulses_proj, sizeof(*pulses_proj) * N_SCF_SHAPES_ST2); /* Size = 4 * N_SCF_SHAPES_ST2 */ + L_search_en = (Word32 *)scratchAlign(L_search_corr, + sizeof(*L_search_corr) * N_SCF_SHAPES_ST2); /* Size = 4 * N_SCF_SHAPES_ST2 */ + enc_pulses_far = (Word16 *)scratchAlign(L_search_en, sizeof(*L_search_en) * N_SCF_SHAPES_ST2); /* Size = 2 * M */ + +#ifdef ENABLE_HR_MODE + proc_target_lp = (Word16 *)buffer_pvq_enc_find_best_submode_pre_post_fx; /* size = 2*M */ +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("processQuantize_stage2ScfEncStage2_fx"); +#endif + + /* fixed setup for a given bitrate of 38 , no moves needed */ + /* k_far = sns_Kval[3][0]; */ + /* k_near = sns_Kval[2][0]; */ + /* kA = sns_Kval[1][0]; */ /* regular, regular_lf */ + /* kB is always 1 */ + + /* NB these search indecese do not correspond exactly to specification shape_index j */ + + pulses_fin[0] = sns_Kval[3][0]; /* far 6 */ + pulses_fin[1] = sns_Kval[2][0]; /* near 8 */ + pulses_fin[2] = sns_Kval[1][0]; /* section A 10 */ + pulses_fin[3] = sns_Kval[0][1]; /* section B 1 */ + + pulses_proj[0] = sns_Kval[3][0]; + pulses_proj[1] = 0; + pulses_proj[2] = 0; + pulses_proj[3] = 0; + + /* pre_process */ +#ifdef ENABLE_HR_MODE + dct32_fx(target_st2, proc_target); /* enc analysis */ + downshift_w32_arr(proc_target, proc_target_lp, 16, M); + + /* get the initial four integer shape candidate vectors, no normalization at this stage */ + pvq_enc_search_fx(proc_target_lp, enc_pulses_far, enc_pulses_near, enc_pulsesA, enc_pulsesB, L_search_corr, + L_search_en, pulses_fin, pulses_proj, M, N_SETA); +#else + Word32 target_st2_32[M]; Word32 proc_target_32[M]; int i; + + FOR (i = 0; i < M; i++) + { + target_st2_32[i] = L_shl_pos(target_st2[i], 16); + } + + dct32_fx(target_st2_32, proc_target_32); /* enc analysis */ + + downshift_w32_arr(proc_target_32, proc_target, 16, M); + + /* get the initial four integer shape candidate vectors, no normalization at this stage */ + pvq_enc_search_fx(proc_target, enc_pulses_far, enc_pulses_near, enc_pulsesA, enc_pulsesB, L_search_corr, + L_search_en, pulses_fin, pulses_proj, M, N_SETA); +#endif + + /* scale with gains a after a unit energy fwd transform */ + /* apply transform to each candidate shape vector priot to gain-shape search loop */ + submode = submodes; /* used as input solely to debug/unit test a specific shape mode */ + + /*target should be in a linearized residual domain target */ + /* search pre, synthesis post*/ + pvq_enc_find_best_submode_pre_post_fx(proc_target, enc_pulses_far, enc_pulses_near, enc_pulsesA, enc_pulsesB, + &submode, &i_gain, st2_vector, + buffer_pvq_enc_find_best_submode_pre_post_fx); /* Q14 tr out */ + + /* send parameters to multiplexor as a series/vector of Long Words */ + /* 0 : 0..3 submode */ + /* 1 : 0..7 gain_ind */ + /* 2 : 0..1 LeadSign ind */ + /* 3 : 25 bit MPVQ index outl_near or A part */ + /* 4 : 3.7 to 21 bits MPVQ index B part OR -2 */ + + L_prm_idx[0] = L_deposit_l(submode); /* complete submode fwd'ed to ari_codec as 0,1,2,3 */ + + submodeMSB = shr_pos(submode, 1); /* LSB of submode , sent as main submode bit */ + submodeLSB = s_and(submode, 0x1); /* LSB of submode */ /* sent via shape param */ + + /* gain, shape indicese , incl. calls to MPVQ indexing */ + IF (submodeMSB == 0) + { /* regular modes:: j=0(reg=AB) or 1(reg_lf A) */ /* regular mode, with two or one shape indices */ + + /* assume regular_lf part , shape_j == 1 */ + enc_PVQ_OA = + mpvq_index_fx(enc_pulsesA, N_SETA, sns_Kval[submode][0]); /* o : leading_sign_index, index, size, k_val */ + L_prm_idx[2] = L_deposit_l(enc_PVQ_OA.lead_sign_ind); /*LS set A */ + + ASSERT(enc_PVQ_OA.size == (UWord32)sns_MPVQ_Sz[submode][0]); + L_prm_idx[3] = L_add(0L, (Word32)enc_PVQ_OA.index); /* MPVQ shape index set A fractional */ + + /* section B always have low indexing dynamics and is combined into one joint single index */ + IF (submodeLSB == 0) + { /* regular AB , shape_j == 0*/ + L_prm_idx[1] = L_deposit_l(i_gain); /* full established gain idx fwd'ed */ /* 2 possible values */ + enc_PVQ_B = mpvq_index_fx(enc_pulsesB, N_SETB, 1); + ASSERT(((enc_PVQ_B.size << 1)) == + (sns_MPVQ_Sz[submode][1])); /* two lowest indeces indicate all_zero B section */ + + L_tmp = L_shl_pos((Word32)enc_PVQ_B.index, 1); /* 2*section B MPVQ index */ + L_prm_idx[4] = L_add(L_tmp, enc_PVQ_B.lead_sign_ind); move32(); /* add joint section B and LS index */ + + ASSERT(L_prm_idx[4] >= 0 && L_prm_idx[4] < (Word32)sns_MPVQ_Sz[submode][0]); + } + ELSE + { + L_prm_idx[1] = L_deposit_l(i_gain); + /* MSBs of established gain idx */ /* 2 or 4 total possible values */ + L_prm_idx[4] = L_deposit_l(-2); + } + } + ELSE + { + /* outlier modes shape_j= 2(near, LSB=0) or 3(far, LSB=1) */ + + IF (submodeLSB == 0) + { + L_prm_idx[1] = L_deposit_l(i_gain); /* established gain idx */ /* 4 possible values */ + enc_PVQ_OA = mpvq_index_fx(enc_pulses_near, M, + sns_Kval[submode][0]); /* o : leading_sign_index, index, size, k_val */ + ASSERT(enc_PVQ_OA.size == sns_MPVQ_Sz[submode][0]); + L_prm_idx[3] = L_add(0L, enc_PVQ_OA.index); /* MPVQ index fractional bits */ + L_prm_idx[4] = L_deposit_l(-1); /* no gain LSBs */ + } + ELSE + { + L_prm_idx[1] = L_deposit_l(i_gain); /* established gain idx MSBs */ /* all 4 or 8 possible values */ + enc_PVQ_OA = mpvq_index_fx(enc_pulses_far, M, + sns_Kval[submode][0]); /* o : leading_sign_index, index, size, k_val */ + ASSERT(enc_PVQ_OA.size == sns_MPVQ_Sz[submode][0]); + L_prm_idx[3] = L_add(0L, enc_PVQ_OA.index); /* MPVQ index fractional bits */ + L_prm_idx[4] = L_deposit_l(-2); /* */ + } + L_prm_idx[2] = L_deposit_l(enc_PVQ_OA.lead_sign_ind); /* LS shape single bit */ + } + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif +#ifdef DYNMEM_COUNT + Dyn_Mem_Out(); +#endif + return; +} + +static Word16 scfdec_stage2_fx( /* o: ber flag */ + const Word32 *L_prm_idx, /* set to -1 if not used */ +#ifdef ENABLE_HR_MODE + Word32 * st2_vector, /*o: Q14 */ +#else + Word16 * st2_vector, /*o: Q14 */ +#endif + Word8 * scratchBuffer) +{ + /* MPVQ deindexing, gainscaling transform and transform */ +#ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In( + Word16 submode; + Word16 submodeLSB, submodeMSB; + Word16 gValQ13; + Word16 idxB; + Word16 maxK; + Word16 BER_dec; + Word16 *dec_pulses; + Word32 *dec_en1_vec; + Word32 *dec_adj_glob_vec; + ); +#else + Dyn_Mem_Deluxe_In( + Word16 submode; + Word16 submodeLSB, submodeMSB; + Word16 gValQ13; + Word16 idxB; + Word16 maxK; + Word16 BER_dec; + Word16 *dec_pulses; + Word16 *dec_en1_vec; + Word16 *dec_adj_glob_vec; + ); +#endif + +#ifdef WMOPS + BASOP_sub_sub_start("scfdec_stage2_fx"); +#endif + + dec_pulses = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * M = 32 bytes */ +#ifdef ENABLE_HR_MODE + dec_en1_vec = (Word32 *)scratchAlign(dec_pulses, sizeof(*dec_pulses) * M); /* Size = 2 * M = 32 bytes */ + dec_adj_glob_vec = (Word32 *)scratchAlign(dec_en1_vec, sizeof(*dec_en1_vec) * M); /* Size = 2 * M = 32 bytes */ +#else + dec_en1_vec = (Word16 *)scratchAlign(dec_pulses, sizeof(*dec_pulses) * M); /* Size = 2 * M = 32 bytes */ + dec_adj_glob_vec = (Word16 *)scratchAlign(dec_en1_vec, sizeof(*dec_en1_vec) * M); /* Size = 2 * M = 32 bytes */ +#endif + + /* get submode */ + submode = extract_l(L_prm_idx[0]); /* 0..3 */ + + submodeLSB = s_and(submode, 0x1); + submodeMSB = shr_pos(submode, 1); + + /* get initial adjustment gain vector for regular, outl_near */ + ASSERT(L_prm_idx[1] >= 0 && L_prm_idx[1] < sns_gainSz[submode]); + gValQ13 = sns_gaintabPtr[submode][L_prm_idx[1]]; + ASSERT(gValQ13 >= 0); + + /* gain, shape indices, incl.calls to MPVQ deindexing */ + IF (submodeMSB != 0) + { + /* outlier_near or outlier_far mode decoding */ + maxK = sns_Kval[submode][0]; move16(); + BER_dec = pvq_dec_deidx_fx(dec_pulses, maxK, M, extract_l(L_prm_idx[2]), (UWord32)L_prm_idx[3]); + } + ELSE + { /* regular mode, with potentially two shape indices */ + + maxK = sns_Kval[submode][0]; move16(); + BER_dec = pvq_dec_deidx_fx(dec_pulses, maxK, N_SETA, extract_l(L_prm_idx[2]), (UWord32)L_prm_idx[3]); + + IF (submodeLSB == 0) + { + idxB = extract_l(L_prm_idx[4]); /* 0..11 */ + ASSERT(idxB >= 0 && idxB < (Word16)sns_MPVQ_Sz[0][1]); + BER_dec |= pvq_dec_deidx_fx(&(dec_pulses[N_SETA]), sns_Kval[submode][1], N_SETB, s_and(idxB, 0x1), + (UWord32)L_deposit_l(shr_pos(idxB, 1))); + /* maxK does not need to be increased as set B is not stacked */ + } + ELSE + { /* LSB gain bit already parsed */ + ASSERT(L_prm_idx[4] < 0); + basop_memset(&dec_pulses[N_SETA], 0, (N_SETB) * sizeof(*dec_pulses)); + } + } + + /* normalize decoded integer vector , exactly as on encoder side !! */ + pvq_dec_en1_normQ14_fx(dec_en1_vec, dec_pulses, maxK, M); + +#ifdef ENABLE_HR_MODE + idct32_32_fx(dec_en1_vec, dec_adj_glob_vec); +#else + idct16_fx(dec_en1_vec, dec_adj_glob_vec); /* fwd warping in unscaled domain */ +#endif + + /* scaling aligend with encoder search */ + pvq_dec_scale_vec_fx(dec_adj_glob_vec, gValQ13, st2_vector); + +#ifdef WMOPS + BASOP_sub_sub_end(); +#endif + Dyn_Mem_Deluxe_Out(); + return BER_dec; +} + +void processSnsQuantizeScfEncoder_fx(Word16 scf[], /* i: input scf M */ + Word32 *L_prm_idx, /* o: indeces . negative == unused */ +#ifdef ENABLE_HR_MODE + Word32 *scf_q, /* o: quantized scf M */ +#else + Word16 *scf_q, /* o: quantized scf M */ +#endif + Word8 * scratchBuffer) /* Size = 28 * M + 52 */ +{ +#ifdef ENABLE_HR_MODE + Dyn_Mem_Deluxe_In( + Word32 *target_st2; + Word16 *st1_idx; /* stage 1 indices */ + Word8 * buffer_processQuantize_stage2ScfEncStage2_fx; + Counter col; + ); +#else + Dyn_Mem_Deluxe_In( + Word16 *target_st2; + Word16 *st1_idx; /* stage 1 indices */ + Word8 * buffer_processQuantize_stage2ScfEncStage2_fx; + Counter col; + ); +#endif + +#ifdef ENABLE_HR_MODE + target_st2 = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * M */ +#else + target_st2 = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * M */ +#endif + st1_idx = (Word16 *)scratchAlign(target_st2, sizeof(*target_st2) * M); /* Size = 2 * 2 */ + buffer_processQuantize_stage2ScfEncStage2_fx = (Word8 *)scratchAlign(st1_idx, sizeof(*st1_idx) * M); + /* Size = 26 * M + 48 */ + + /* TBD needs update */ + + /* 1st stage trained VQ */ + processQuantize_stage1ScfEncStage1_fx(scf, scf_q, &st1_idx[0], &st1_idx[1]); + L_prm_idx[0] = L_deposit_l(st1_idx[0]); + L_prm_idx[1] = L_deposit_l(st1_idx[1]); + +/* 2nd stage PVQ-based SCF quantizer */ + FOR (col = 0; col < M; col++) + { +#ifdef ENABLE_HR_MODE + target_st2[col] = L_sub(L_deposit_h(scf[col]), scf_q[col]); +#else + target_st2[col] = sub(scf[col], scf_q[col]); +#endif + } + + processQuantize_stage2ScfEncStage2_fx(target_st2, scf_q, &L_prm_idx[2], VQMODES26, /* 0xF means all submodes */ + buffer_processQuantize_stage2ScfEncStage2_fx); /* PVQ in stage 2 */ + Dyn_Mem_Deluxe_Out(); +} + +Word16 processSnsQuantizeScfDecoder_fx( /* o: BER flag */ + Word32 *L_prm_idx, /* i: indeces */ +#ifdef ENABLE_HR_MODE + Word32 scf_q[], +#else + Word16 scf_q[], +#endif + Word8 *scratchBuffer) /* o: M */ +{ + Dyn_Mem_Deluxe_In( + Word16 BER_flag; + ); + + /* Decode First Stage */ +#ifdef ENABLE_HR_MODE + processDeQuantize_stage1ScfDecStage1_fx(st1SCF0_7_base5_32x8_Q27, st1SCF8_15_base5_32x8_Q27, + extract_l(L_prm_idx[0]), extract_l(L_prm_idx[1]), scf_q); +#else + processDeQuantize_stage1ScfDecStage1_fx(st1SCF0_7_base5_32x8_Q11, st1SCF8_15_base5_32x8_Q11, + extract_l(L_prm_idx[0]), extract_l(L_prm_idx[1]), scf_q); +#endif + + /* Decode Second Stage */ + BER_flag = scfdec_stage2_fx(&(L_prm_idx[2]), scf_q, scratchBuffer); + + Dyn_Mem_Deluxe_Out(); + return BER_flag; +} + diff --git a/lib_lc3plus/tinywavein_c.h b/lib_lc3plus/tinywavein_c.h new file mode 100644 index 000000000..32789e314 --- /dev/null +++ b/lib_lc3plus/tinywavein_c.h @@ -0,0 +1,603 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef __TINYWAVEIN_C_H__ +#define __TINYWAVEIN_C_H__ + +/*#define SUPPORT_BWF*/ + +#include +#include +#include + +#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || defined(__arm__) || \ + defined(__aarch64__) +#define __TWI_LE /* _T_iny _W_ave _I_n _L_ittle _E_ndian */ +#endif + +#if defined(__POWERPC__) +#define __TWI_BE /* _T_iny _W_ave _I_n _B_ig _E_ndian */ +#endif + +#if !defined(__TWI_LE) && !defined(__TWI_BE) +#error unknown processor +#endif + +#define __TWI_SUCCESS (0) +#define __TWI_ERROR (-1) + +#ifdef SUPPORT_BWF +typedef struct +{ + float loudnessVal; + float loudnessRange; + float maxTruePeakLevel; + float maxMomentaryLoudnes; + float maxShortTermLoudness; +} WAVEIN_LOUDNESSINFO; +#endif + +typedef struct __tinyWaveInHandle +{ + FILE * theFile; + fpos_t dataChunkPos; + unsigned int position; + unsigned int length; + unsigned int bps; +#ifdef SUPPORT_BWF + WAVEIN_LOUDNESSINFO *loudnessInfo; +#endif +} __tinyWaveInHandle, WAVEFILEIN; + +typedef struct +{ + short compressionCode; + short numberOfChannels; + unsigned int sampleRate; + unsigned int averageBytesPerSecond; + short blockAlign; + short bitsPerSample; + /* short extraFormatBytes ; */ +} SWavInfo; + +#ifdef SUPPORT_BWF +typedef struct +{ + unsigned char description[256]; + unsigned char originator[32]; + unsigned char originatorReference[32]; + unsigned char originatorDate[10]; /* ASCII: <> */ + unsigned char originationTime[8]; /* ASCII: <> */ + unsigned int timeReferenceLow; + unsigned int timeReferenceHigh; + unsigned short version; + unsigned char UMID[64]; /* Binary Bytes of SMPTE UMID */ + + signed short loudnessVal; + signed short loudnessRange; + signed short maxTruePeakLevel; + signed short maxMomentaryLoudnes; + signed short maxShortTermLoudness; + + unsigned char Reserved[180]; + + unsigned char codingHistory; /* ASCII: <> */ +} SBwfWav; +#endif + +typedef struct +{ + char chunkID[4]; + unsigned int chunkSize; + /* long dataOffset ; */ /* never used */ +} SChunk; + +/* local wrapper, always returns correct endian */ +static size_t fread_LE(void *ptr, size_t size, size_t nmemb, FILE *stream); + +#ifdef __TWI_BE +static short BigEndian16(short v); +static int BigEndian32(int v); +#endif + +/*! + * \brief Read header from a WAVEfile. Host endianess is handled accordingly. + * \fp filepointer of type FILE*. + * \wavinfo SWavInfo struct where the decoded header info is stored into. + * \return 0 on success and non-zero on failure. + * + */ +static WAVEFILEIN *OpenWav(const char *filename, unsigned int *samplerate, short *channels, unsigned int *samplesInFile, + short *bps) +{ + WAVEFILEIN *self; + + SChunk fmt_chunk, data_chunk; + int offset; + unsigned int tmpSize; + char tmpFormat[4]; + SWavInfo wavinfo = {0, 0, 0, 0, 0, 0}; + + self = (WAVEFILEIN *)calloc(1, sizeof(WAVEFILEIN)); + if (!self) + goto bail; /* return NULL; */ + + if (!filename) + goto bail; + if (!samplerate) + goto bail; + if (!channels) + goto bail; + if (!samplesInFile) + goto bail; + if (!bps) + goto bail; + + self->theFile = fopen(filename, "rb"); + if (!self->theFile) + goto bail; + + /* read RIFF-chunk */ + if (fread(tmpFormat, 1, 4, self->theFile) != 4) + { + goto bail; + } + + if (strncmp("RIFF", tmpFormat, 4)) + { + goto bail; + } + + /* Read RIFF size. Ignored. */ + fread_LE(&tmpSize, 4, 1, self->theFile); + + /* read WAVE-chunk */ + if (fread(tmpFormat, 1, 4, self->theFile) != 4) + { + goto bail; + } + + if (strncmp("WAVE", tmpFormat, 4)) + { + goto bail; + } + + /* read format/bext-chunk */ + if (fread(fmt_chunk.chunkID, 1, 4, self->theFile) != 4) + { + goto bail; + } + +#ifdef SUPPORT_BWF + /* test for bext-chunk */ + if (!strncmp("bext", fmt_chunk.chunkID, 4)) + { + /*unsigned int i;*/ + unsigned int bextSize = 0; + + if (fread_LE(&bextSize, 1, 4, self->theFile) != 4) + { + goto bail; + } + + self->loudnessInfo = (WAVEIN_LOUDNESSINFO *)calloc(1, sizeof(WAVEIN_LOUDNESSINFO)); + + if (bextSize >= 602) + { /* minimum size bext-data, w/o 'CodingHistory' */ + int i; + signed short readBuf = 0; + signed int nulbuf = 0; + + /* first skip all descriptive data */ + for (i = 0; i < 412; i++) + { + if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) + { + goto bail; + } + bextSize -= 1; + } + /* second, read loudness data */ + fread_LE(&readBuf, 2, 1, self->theFile); + bextSize -= 2; + self->loudnessInfo->loudnessVal = (float)readBuf * 0.01f; + + fread_LE(&readBuf, 2, 1, self->theFile); + bextSize -= 2; + self->loudnessInfo->loudnessRange = (float)readBuf * 0.01f; + + fread_LE(&readBuf, 2, 1, self->theFile); + bextSize -= 2; + self->loudnessInfo->maxTruePeakLevel = (float)readBuf * 0.01f; + + fread_LE(&readBuf, 2, 1, self->theFile); + bextSize -= 2; + self->loudnessInfo->maxMomentaryLoudnes = (float)readBuf * 0.01f; + + fread_LE(&readBuf, 2, 1, self->theFile); + bextSize -= 2; + self->loudnessInfo->maxShortTermLoudness = (float)readBuf * 0.01f; + + /* skip reserved data */ + for (i = 0; i < 180; i++) + { + if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) + { + goto bail; + } + bextSize -= 1; + } + } + + /* skip remaining data */ + while (bextSize) + { + int nulbuf; + if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) + { + goto bail; + } + bextSize -= 1; + } + + /* read next chunk header */ + if (fread(fmt_chunk.chunkID, 1, 4, self->theFile) != 4) + { + goto bail; + } + } +#endif + + /* skip some potential chunks up to fmt chunk */ + + while (strncmp("fmt ", fmt_chunk.chunkID, 4) != 0) + { + unsigned int chunkSize = 0; + + if (fread_LE(&chunkSize, 1, 4, self->theFile) != 4) + { + goto bail; + } + + /* skip chunk data */ + while (chunkSize) + { + int nulbuf; + if (fread_LE(&nulbuf, 1, 1, self->theFile) != 1) + { + goto bail; + } + chunkSize -= 1; + } + + /* read next chunk header */ + if (fread(fmt_chunk.chunkID, 1, 4, self->theFile) != 4) + { + goto bail; + } + } + + /* go on with fmt-chunk */ + if (strncmp("fmt ", fmt_chunk.chunkID, 4)) + { + goto bail; + } + + if (fread_LE(&fmt_chunk.chunkSize, 4, 1, self->theFile) != 1) + { /* should be 16 for PCM-format (uncompressed) */ + goto bail; + } + + + /* read info */ + fread_LE(&(wavinfo.compressionCode), 2, 1, self->theFile); + fread_LE(&(wavinfo.numberOfChannels), 2, 1, self->theFile); + fread_LE(&(wavinfo.sampleRate), 4, 1, self->theFile); + fread_LE(&(wavinfo.averageBytesPerSecond), 4, 1, self->theFile); + fread_LE(&(wavinfo.blockAlign), 2, 1, self->theFile); + fread_LE(&(wavinfo.bitsPerSample), 2, 1, self->theFile); + + if (wavinfo.compressionCode == -2) + { + fseek(self->theFile, 8, SEEK_CUR); // skip channel mask + fread_LE(&(wavinfo.compressionCode), 2, 1, self->theFile); // part of GUID + fseek(self->theFile, 14, SEEK_CUR); // skip rest of GUID + offset = fmt_chunk.chunkSize - 40; + } + else + offset = fmt_chunk.chunkSize - 16; + + if (wavinfo.compressionCode == 0x01) + { + if ((wavinfo.bitsPerSample != 16) && (wavinfo.bitsPerSample != 24) && (wavinfo.bitsPerSample != 32)) + /* we do only support 16,24 and 32 bit PCM audio */ + goto bail; + } + else + { + /* if(wavinfo.bitsPerSample != 32) */ + printf("compressioncode: %02x\n", wavinfo.compressionCode); + puts("Error! We only support 16,24 and 32 bit PCM audio"); + exit(1); + goto bail; + } + + /* Skip rest of fmt header if any. */ + for (; offset > 0; offset--) + { + fread(&tmpSize, 1, 1, self->theFile); + } + + do + { + + /* Read data chunk ID */ + if (fread(data_chunk.chunkID, 1, 4, self->theFile) != 4) + { + goto bail; + } + + /* Read chunk length. */ + + if (fread_LE(&offset, 4, 1, self->theFile) != 1) + { + goto bail; + } + + /* Check for data chunk signature. */ + if (strncmp("data", data_chunk.chunkID, 4) == 0) + { + data_chunk.chunkSize = offset; + break; + } + + /* unused 1 byte present, if size is odd */ + /* see https://www.daubnet.com/en/file-format-riff */ + if (offset % 2) + { + offset++; + } + + /* Jump over non data chunk. */ + for (; offset > 0; offset--) + { + fread(&tmpSize, 1, 1, self->theFile); + } + + } while (!feof(self->theFile)); + + /* success so far */ + *samplerate = wavinfo.sampleRate; + *channels = wavinfo.numberOfChannels; + *samplesInFile = data_chunk.chunkSize / wavinfo.numberOfChannels; + *samplesInFile /= ((wavinfo.bitsPerSample + 7) / 8); + *bps = wavinfo.bitsPerSample; + + self->position = 0; + self->bps = wavinfo.bitsPerSample; + self->length = *samplesInFile * wavinfo.numberOfChannels; + + fgetpos(self->theFile, &self->dataChunkPos); + + return self; + +bail: + free(self); + return NULL; +} + +#ifdef SUPPORT_BWF +static void ReadBWF(WAVEFILEIN *self, WAVEIN_LOUDNESSINFO **wavInLoudness) +{ + *wavInLoudness = self->loudnessInfo; +} +#endif + +static int __ReadSample16(WAVEFILEIN *self, int *sample) +{ + size_t cnt; + short v = 0; + + cnt = fread(&v, 2, 1, self->theFile); + + if (cnt != 1) + { + return __TWI_ERROR; + } + + self->position += 1; + +#ifdef __TWI_BE + v = BigEndian16(v); +#endif + *sample = v; + return __TWI_SUCCESS; +} + +static int __ReadSample24(WAVEFILEIN *self, int *sample) +{ + size_t cnt; + int v = 0; + + cnt = fread(&v, 3, 1, self->theFile); + + if (cnt != 1) + { + return __TWI_ERROR; + } + + self->position += 1; + +#ifdef __TWI_BE + v = BigEndian32(v); +#endif + + if (v >= 0x800000) + { + v |= 0xff000000; + } + + *sample = v; + + return __TWI_SUCCESS; +} + +static int __ReadSample32(WAVEFILEIN *self, int *sample) +{ + size_t cnt; + int v = 0; + + cnt = fread(&v, 4, 1, self->theFile); + + if (cnt != 1) + { + return __TWI_ERROR; + } + + self->position += 1; + +#ifdef __TWI_BE + v = BigEndian32(v); +#endif + + *sample = v >> 8; + + return __TWI_SUCCESS; +} + +static int __ReadSampleInternal(WAVEFILEIN *self, int *sample, int scale) +{ + int err; + + if (!self) + { + return __TWI_ERROR; + } + + switch (scale) + { + + case 16: err = __ReadSample16(self, sample); break; + + case 24: err = __ReadSample24(self, sample); break; + + case 32: err = __ReadSample32(self, sample); break; + + default: err = __TWI_ERROR; break; + } + + return err; +} + +/* this function returns normalized values in the range +8388607..-8388608 */ +static int ReadWavInt(WAVEFILEIN *self, int sampleBuffer[], unsigned int nSamplesToRead, unsigned int *nSamplesRead) +{ + unsigned int i; + int err = __TWI_SUCCESS; + *nSamplesRead = 0; + + if (!sampleBuffer) + { + return __TWI_ERROR; + } + + /* check if we have enough samples left, if not, + set nSamplesToRead to number of samples left. */ + if (self->position + nSamplesToRead > self->length) + { + nSamplesToRead = self->length - self->position; + } + + for (i = 0; i < nSamplesToRead; i++) + { + + int tmp; + err = __ReadSampleInternal(self, &tmp, self->bps); + if (err != __TWI_SUCCESS) + { + return err; + } + sampleBuffer[i] = tmp; + *nSamplesRead += 1; + } + + return __TWI_SUCCESS; +} + +static int CloseWavIn(WAVEFILEIN *self) +{ + if (self) + { + if (self->theFile) + { + fclose(self->theFile); + } + } + free(self); + + return __TWI_SUCCESS; +} +/* +static int ResetWavIn(WAVEFILEIN* self) +{ + if (self) { + if (self->theFile) { + fsetpos(self->theFile, &self->dataChunkPos); + self->position = 0; + } + } + return __TWI_SUCCESS; +} +*/ +/*------------- local subs ----------------*/ + +static size_t fread_LE(void *ptr, size_t size, size_t nmemb, FILE *stream) +{ +#ifdef __TWI_LE + return fread(ptr, size, nmemb, stream); +#endif +#ifdef __TWI_BE + + unsigned char x[sizeof(int)]; + unsigned char *y = (unsigned char *)ptr; + int i; + int len; + + len = fread(x, size, nmemb, stream); + + for (i = 0; i < size * nmemb; i++) + { + *y++ = x[size * nmemb - i - 1]; + } + + return len; +#endif +} + +#ifdef __TWI_BE +static short BigEndian16(short v) +{ + short a = (v & 0x0ff); + short b = (v & 0x0ff00) >> 8; + + return a << 8 | b; +} + +static int BigEndian32(int v) +{ + int a = (v & 0x0ff); + int b = (v & 0x0ff00) >> 8; + int c = (v & 0x0ff0000) >> 16; + int d = (v & 0xff000000) >> 24; + + return a << 24 | b << 16 | c << 8 | d; +} +#endif + +#endif /* __TINYWAVEIN_C_H__ */ diff --git a/lib_lc3plus/tinywaveout_c.h b/lib_lc3plus/tinywaveout_c.h new file mode 100644 index 000000000..672254270 --- /dev/null +++ b/lib_lc3plus/tinywaveout_c.h @@ -0,0 +1,889 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef __TINYWAVEOUT_C_H__ +#define __TINYWAVEOUT_C_H__ + +/*#define TWO_SUPPORT_BWF*/ + +#include +#include +#include +#include +#ifdef TWO_SUPPORT_BWF +#include +#endif + +/***** Interface *********************************************************/ + +#ifndef TWO_UINT64 + #if !(defined(WIN32)) + #include + #define TWO_UINT64 uint64_t + #else + #define TWO_UINT64 unsigned __int64 + #endif +#endif + +typedef struct WAVEFILEOUT WAVEFILEOUT; +#ifdef TWO_SUPPORT_BWF +typedef struct WAVEOUT_LOUDNESSINFO WAVEOUT_LOUDNESSINFO; +#endif + +#define __TWO_SUCCESS (0) +#define __TWO_ERROR (-1) + +static WAVEFILEOUT* CreateWav( + const char *fileName, + const unsigned int sampleRate, + const unsigned int numChannels, + const unsigned int bps + ); + +#ifdef TWO_SUPPORT_BWF +static WAVEFILEOUT* CreateWavBWF( + const char *fileName, + const unsigned int sampleRate, + const unsigned int numChannels, + const unsigned int bps, + const WAVEOUT_LOUDNESSINFO *hBwfData + ); +#endif + +/* this function expects values in the 16 bit range +32767..-32768 */ +static int WriteWavShort( + WAVEFILEOUT* self, + short sampleBuffer[], + unsigned int nSamples + ); + +/* this function expects values in the 24 bit range +8388607..-8388608 */ +static int WriteWavLong( + WAVEFILEOUT* self, + int sampleBuffer[], + unsigned int nSamples + ); + +/* this function expects normalized values in the range +-1.0f */ +static int WriteWavFloat( + WAVEFILEOUT* self, + float sampleBuffer[], + unsigned int nSamples + ); + +static int CloseWav(WAVEFILEOUT* self); +#ifdef TWO_SUPPORT_BWF +static int CloseWavBWF(WAVEFILEOUT* self, WAVEOUT_LOUDNESSINFO bextData); +#endif + +/***** Implementation *********************************************************/ + +#if defined (__i386__) || defined (_M_IX86) || defined (_M_X64) || defined (__x86_64__) || defined (__arm__) || defined (__xtensa__) || defined (__aarch64__) || defined (__EMSCRIPTEN__) +#define __TWO_LE /* _T_iny _W_ave _O_ut _L_ittle _E_ndian */ +#endif + +#if defined (__POWERPC__) +#define __TWO_BE /* _T_iny _W_ave _O_ut _B_ig _E_ndian */ +#endif + +#if defined (__sparc__) +#define __TWO_BE /* _T_iny _W_ave _O_ut _B_ig _E_ndian */ +#endif + +#if ! defined (__TWO_LE) && ! defined (__TWO_BE) +#error unknown processor +#endif + +/*--- local types/structs ----------------------------------*/ + +#if defined(_MSC_VER) + #pragma pack(push, 1) +#else + #pragma pack(1) +#endif + + +#ifdef TWO_SUPPORT_BWF +struct WAVEOUT_LOUDNESSINFO { + float loudnessVal; + float loudnessRange; + float maxTruePeakLevel; + float maxMomentaryLoudnes; + float maxShortTermLoudness; +}; +#endif + + +typedef struct __tinyWaveOutHeader +{ + unsigned int riffType; /* 'RIFF/RF64' */ + unsigned int riffSize; /* file size/-1 */ + unsigned int waveType; /* 'WAVE' */ +} __tinyWaveOutHeader; + +typedef struct __tinyWaveOutDs64Chunk +{ + unsigned int formatType; /* = 'JUNK/ds64' */ + unsigned int formatSize; /* size info */ + TWO_UINT64 riffSize64; + TWO_UINT64 dataSize64; + TWO_UINT64 sampleCount64; + unsigned int tableLength; /* optional tables, always 0 for tinywaveout */ + /* here: optional tables */ +} __tinyWaveOutDs64Chunk; + +#ifdef TWO_SUPPORT_BWF +typedef struct __tinyWaveOutBextChunk +{ + unsigned int formatType; /* = 'bext' */ + unsigned int formatSize; /* size info */ + + unsigned char description[256]; + unsigned char originator[32]; + unsigned char originatorReference[32]; + unsigned char originatorDate[10]; /* ASCII: <> */ + unsigned char originationTime[8]; /* ASCII: <> */ + unsigned int timeReferenceLow; + unsigned int timeReferenceHigh; + unsigned short version; + unsigned char UMID[64]; /* Binary Bytes of SMPTE UMID */ + + signed short loudnessVal; + signed short loudnessRange; + signed short maxTruePeakLevel; + signed short maxMomentaryLoudnes; + signed short maxShortTermLoudness; + + unsigned char Reserved[180]; + + unsigned char codingHistory; /* ASCII: <> - undefined length! */ + /* for variable length, mve this out of this struct */ +} __tinyWaveOutBextChunk; +#endif + +typedef struct __tinyWaveOutFmtChunk +{ + unsigned int formatType; + unsigned int formatSize; + + unsigned short formatTag; + unsigned short numChannels; + unsigned int sampleRate; + unsigned int bytesPerSecond; + unsigned short blockAlignment; + unsigned short bitsPerSample; + + /* wav fmt ext hdr here */ +} __tinyWaveOutFmtChunk; + +typedef struct __tinyWaveOutDataChunk +{ + unsigned int dataType; + unsigned int dataSize; + +} __tinyWaveOutDataChunk; + + +struct WAVEFILEOUT { + /* for reasons of memory alignment, have 64 bit data types first */ + TWO_UINT64 dataSize; + TWO_UINT64 dataSizeLimit; /* maximum size for data chunk for 4 GB files */ + TWO_UINT64 dataSizeLimit64; /* maximum size for data chunk for 2^64 B addressable files */ + TWO_UINT64 clipCount; + FILE* theFile; + unsigned int junkChunkOffset; + unsigned int fmtChunkOffset; +#ifdef TWO_SUPPORT_BWF + unsigned int bextChunkOffset; +#endif + unsigned int dataChunkOffset; + unsigned int bps; + + /* only needed for RF64: */ + unsigned int blockAlign; /* only needed for close() of ds64 chunk */ +}; + + +/*--- local protos --------------------------------------------------*/ +static __inline unsigned int BigEndian32(char, char, char, char); +static __inline unsigned int LittleEndian32(unsigned int); +static __inline unsigned int LittleEndian32s(int); +static __inline short LittleEndian16(short); +static __inline TWO_UINT64 LittleEndian64(TWO_UINT64); +#ifdef TWO_SUPPORT_BWF +static unsigned int EncodeLoudness(float); +#endif +static __inline int __dataSizeChk( WAVEFILEOUT* self, int newbytes ); + +#if defined(_MSC_VER) + #pragma pack(pop) +#else + #pragma pack() +#endif + + +#ifdef TWO_SUPPORT_BWF +static void setDefaultLoudness(WAVEOUT_LOUDNESSINFO *x) +{ + x->loudnessVal = 1.0f; + x->loudnessRange = 2.0f; + x->maxTruePeakLevel = 3.0f; + x->maxMomentaryLoudnes = 4.0f; + x->maxShortTermLoudness = 5.0f; +} +#endif + +static WAVEFILEOUT* __CreateWavInternal( + const char *fileName, + const unsigned int sampleRate, + const unsigned int numChannels, + const unsigned int bps +#ifdef TWO_SUPPORT_BWF + , + const WAVEOUT_LOUDNESSINFO *hBwfData +#endif + ) +{ + WAVEFILEOUT* self = NULL; + __tinyWaveOutHeader whdr; + __tinyWaveOutDs64Chunk ds64ch; +#ifdef TWO_SUPPORT_BWF + __tinyWaveOutBextChunk wbextch; +#endif + __tinyWaveOutFmtChunk wfch; + __tinyWaveOutDataChunk wdch; + unsigned int blockAlignment = 0; + unsigned int ByteCnt = 0; /* Byte counter for fwrite */ + + /* pseudo use to avoid unused symbols */ + (void)WriteWavShort; + (void)WriteWavLong; + (void)WriteWavFloat; +#ifdef TWI_SUPPORT_BWF + (void)CreateWavBWF; + (void)CloseWavBWF; + (void)setDefaultLoudness; +#endif + + /* param check */ + if (!fileName) goto bail; + if (sampleRate == 0) goto bail; + if (sampleRate > 768000) goto bail; + if (numChannels == 0) goto bail; + if (numChannels > 64) goto bail; + if (bps != 16 && bps != 24 && bps != 32) goto bail; + + self = (WAVEFILEOUT*)calloc(1, sizeof(WAVEFILEOUT)); + if (!self) goto bail; /* return NULL; */ + + self->theFile = fopen(fileName, "wb+"); + if (!self->theFile) goto bail; + + /* WAV-Header */ + whdr.riffType = BigEndian32('R','I','F','F'); + whdr.riffSize = LittleEndian32(0xffffffff); /* set to maximum, if fseek() doesn't work later */ + whdr.waveType = BigEndian32('W','A','V','E'); + /* write to file */ + ByteCnt = 0; + ByteCnt += fwrite(&whdr, 1, sizeof(whdr), self->theFile); + + /* ds64/JUNK-Chunk */ + ds64ch.formatType = BigEndian32('J','U','N','K'); + ds64ch.formatSize = LittleEndian32(sizeof(__tinyWaveOutDs64Chunk) - 8); + ds64ch.riffSize64 = (TWO_UINT64) -1; + ds64ch.dataSize64 = (TWO_UINT64) -1; + ds64ch.sampleCount64 = (TWO_UINT64) -1; + ds64ch.tableLength = 0; + self->junkChunkOffset = ByteCnt; + ByteCnt += fwrite(&ds64ch, 1, sizeof(ds64ch), self->theFile); + +#ifdef TWO_SUPPORT_BWF + /* BEXT-Chunk */ + if (hBwfData) { + memset(&wbextch, 0, sizeof(__tinyWaveOutBextChunk)); + wbextch.formatType = BigEndian32('b','e','x','t'); + wbextch.formatSize = LittleEndian32(sizeof(__tinyWaveOutBextChunk) - 8); + wbextch.version = 0x0002; + wbextch.loudnessVal = EncodeLoudness(hBwfData->loudnessVal); + wbextch.loudnessRange = EncodeLoudness(hBwfData->loudnessRange); + wbextch.maxTruePeakLevel = EncodeLoudness(hBwfData->maxTruePeakLevel); + wbextch.maxMomentaryLoudnes = EncodeLoudness(hBwfData->maxMomentaryLoudnes); + wbextch.maxShortTermLoudness = EncodeLoudness(hBwfData->maxShortTermLoudness); + /* t.b.d.: more values */ + + /* write to file */ + self->bextChunkOffset = ByteCnt; + ByteCnt += fwrite(&wbextch, 1, sizeof(wbextch), self->theFile); + } +#endif + + /* FMT-Chunk */ + wfch.formatType = BigEndian32('f','m','t',' '); + wfch.formatSize = LittleEndian32(16); + switch (bps) { + case 16: + case 24: + wfch.formatTag = LittleEndian16(0x0001); /* WAVE_FORMAT_PCM */ + break; + case 32: + wfch.formatTag = LittleEndian16(0x0003); /* WAVE_FORMAT_IEEE_FLOAT */ + break; + default: + goto bail; + } + self->bps = bps; + wfch.bitsPerSample = LittleEndian16(bps); + wfch.numChannels = LittleEndian16(numChannels); + blockAlignment = numChannels * (bps >> 3); + wfch.blockAlignment = LittleEndian16(blockAlignment); + wfch.sampleRate = LittleEndian32(sampleRate); + wfch.bytesPerSecond = LittleEndian32(sampleRate * blockAlignment); + /* tbd: wavfmt ext hdr here */ + /* write to file */ + self->fmtChunkOffset = ByteCnt; + ByteCnt += fwrite(&wfch, 1, sizeof(wfch), self->theFile); + + /* DATA-Chunk */ + self->dataChunkOffset = ByteCnt; + wdch.dataType = BigEndian32('d','a','t','a'); + wdch.dataSize = LittleEndian32(0xffffffff - ByteCnt); /* yet unknown. set to maximum of 4 GB file */ + /* write to file */ + ByteCnt += fwrite(&wdch, 1, sizeof(wdch), self->theFile); + + self->dataSize = 0; + + /* self->dataSizeLimit = 0x7fffffff - ByteCnt; */ /* maximum size for data chunk for 2 GB files */ + self->dataSizeLimit = 0xffffffff - ByteCnt; /* maximum size for data chunk for 4 GB files */ + self->dataSizeLimit64 = 0xffffffffffffffff - ByteCnt; /* maximum size for data chunk for 64 bit addressable files */ + + self->clipCount = 0; + self->blockAlign = blockAlignment; + + return self; + + bail: + if ( NULL != self) { + free(self); + } + + return NULL; +} + +static WAVEFILEOUT* CreateWav( + const char* fileName, + const unsigned int sampleRate, + const unsigned int numChannels, + const unsigned int bps + ) +{ +#ifdef TWO_SUPPORT_BWF + return __CreateWavInternal(fileName, sampleRate, numChannels, bps, NULL); +#else + return __CreateWavInternal(fileName, sampleRate, numChannels, bps); +#endif +} + +#ifdef TWO_SUPPORT_BWF +static WAVEFILEOUT* CreateWavBWF( + const char *fileName, + const unsigned int sampleRate, + const unsigned int numChannels, + const unsigned int bps, + const WAVEOUT_LOUDNESSINFO *hBwfData + ) +{ + return __CreateWavInternal(fileName, sampleRate, numChannels, bps, hBwfData); +} +#endif + +#define MAX_PCM16 (+32767) +#define MIN_PCM16 (-32768) +static __inline int CLIP_PCM16(int sample, TWO_UINT64* clipcount) +{ + int tmp = sample; + + if (sample >= MAX_PCM16) { + tmp = MAX_PCM16; + (*clipcount)++; + } else { + if (sample <= MIN_PCM16) { + tmp = MIN_PCM16; + (*clipcount)++; + } + } + + return tmp; +} + +#define MAX_PCM24 (+8388607) +#define MIN_PCM24 (-8388608) +static __inline int CLIP_PCM24(int sample, TWO_UINT64* clipcount) +{ + int tmp = sample; + + if (sample >= MAX_PCM24) { + tmp = MAX_PCM24; + (*clipcount)++; + } else { + if (sample <= MIN_PCM24) { + tmp = MIN_PCM24; + (*clipcount)++; + } + } + + return tmp; +} + +#define MAX_FLOAT32 (+1.0f) +#define MIN_FLOAT32 (-1.0f) +static __inline float CLIP_FLOAT32(float sample, TWO_UINT64* clipcount) +{ + float tmp = sample; + + if (sample >= MAX_FLOAT32) { + tmp = MAX_FLOAT32; + (*clipcount)++; + } else { + if (sample <= MIN_FLOAT32) { + tmp = MIN_FLOAT32; + (*clipcount)++; + } + } + + return tmp; +} + + + +static int __WriteSample16( + WAVEFILEOUT* self, + int sample, + int scale + ) +{ + size_t cnt; + short v; + + if ((scale - 16) > 0) + sample = sample >> (scale - 16); + else + sample = (int) ((uint32_t) sample << (16 - scale)); + + v = (short)CLIP_PCM16(sample, &(self->clipCount)); +#ifdef __TWO_BE + v = LittleEndian16(v); +#endif + + cnt = fwrite(&v, sizeof(short), 1, self->theFile); + + if (cnt == 1) { + self->dataSize += 2; + return __TWO_SUCCESS; + } + + return __TWO_ERROR; +} + + +static int __WriteSample24( + WAVEFILEOUT* self, + int sample, + int scale + ) +{ + size_t cnt; + int v; + + if ((scale - 24) > 0) + sample = sample >> (scale - 24); + else + sample = (int) (((unsigned int)sample) << (24 - scale)); + + v = (int)CLIP_PCM24(sample, &(self->clipCount)); +#ifdef __TWO_BE + v = LittleEndian32s(v); +#endif + cnt = fwrite(&v, 3, 1, self->theFile); + + if (cnt == 1) { + self->dataSize += 3; + return __TWO_SUCCESS; + } + + return __TWO_ERROR; +} + + +static int __WriteSample32( + WAVEFILEOUT* self, + float sample + ) +{ + size_t cnt; + union fl_int { + float v_float; + int v_int; + }; + union fl_int v; + +#if CLIP_FLOAT + v.v_float = CLIP_FLOAT32(sample, &(self->clipCount)); +#else + v.v_float = sample; + if((sample > 1.0f) || (sample <-1.0f)) + self->clipCount++; +#endif + +#ifdef __TWO_BE + v.v_int = LittleEndian32s(v.v_int); +#endif + cnt = fwrite(&v, 4, 1, self->theFile); + + if (cnt == 1) { + self->dataSize += 4; + return __TWO_SUCCESS; + } + + return __TWO_ERROR; +} + + +static int __WriteSampleInt( + WAVEFILEOUT* self, + int sample, + int scale + ) +{ + int err; + + if (!self) return __TWO_ERROR; + + + switch (self->bps) { + + case 16: + err = __WriteSample16(self, sample, scale); + break; + + case 24: + err = __WriteSample24(self, sample, scale); + break; + + default: + err = __TWO_ERROR; + break; + } + + return err; +} + + +/* this function expects values in the 16 bit range +-32767/8 */ +static int WriteWavShort( + WAVEFILEOUT* self, + short sampleBuffer[], + unsigned int nSamples + ) +{ + unsigned long i; + int err = __TWO_SUCCESS; + + if (!self) return __TWO_ERROR; + if (!sampleBuffer) return __TWO_ERROR; + if (__dataSizeChk(self, nSamples * sizeof(short))) return __TWO_ERROR; + + for (i=0; i< nSamples; i++) { + if (self->bps == 32) + { + err = __WriteSample32(self, sampleBuffer[i] / 32768.0f); + } + else + { + err = __WriteSampleInt(self, (int)sampleBuffer[i], 16); + } + if (err != __TWO_SUCCESS) return err; + } + + return __TWO_SUCCESS; +} + + +/* this function expects values in the 24 bit range +-8388607/8 */ +static int WriteWavLong( + WAVEFILEOUT* self, + int sampleBuffer[], + unsigned int nSamples + ) +{ + unsigned long i; + int err = __TWO_SUCCESS; + + if (!self) return __TWO_ERROR; + if (!sampleBuffer) return __TWO_ERROR; + if (__dataSizeChk(self, nSamples * sizeof(int))) return __TWO_ERROR; + + for (i = 0; i < nSamples; i++) { + if (self->bps == 32) + { + err = __WriteSample32(self, sampleBuffer[i] / 8388608.0f); + } + else + { + err = __WriteSampleInt(self, sampleBuffer[i], 24); + } + if (err != __TWO_SUCCESS) return err; + } + + return __TWO_SUCCESS; +} + + +/* this function expects normalized values in the range +-1.0 */ +#define MAX_FL (+2.0f * 8388608.0f ) +#define MIN_FL (-2.0f * 8388608.0f ) +#define CLIP_FL(x) ( ((x) >= MAX_FL) ? MAX_FL : (((x) <= MIN_FL) ? MIN_FL : (x)) ) +static int WriteWavFloat( + WAVEFILEOUT* self, + float sampleBuffer[], + unsigned int nSamples + ) +{ + unsigned int i; + int err = __TWO_SUCCESS; + + if (!self) return __TWO_ERROR; + if (!sampleBuffer) return __TWO_ERROR; + if (__dataSizeChk(self, nSamples * sizeof(float))) return __TWO_ERROR; + + for (i=0; ibps == 32) + { + err = __WriteSample32(self, sampleBuffer[i]); + } + else + { + float tmp = CLIP_FL(sampleBuffer[i] * 8388608.0f); /* CLIP_FL is just to avoid an INT overrun before the actual cast to int, real clipping and counting is done below */ + err = __WriteSampleInt(self, (int) tmp, 24); + } + if (err != __TWO_SUCCESS) return err; + } + + return __TWO_SUCCESS; +} + + +static int CloseWav(WAVEFILEOUT* self) +{ + unsigned int riffSize_le = 0; + unsigned int dataSize_le = 0; + TWO_UINT64 riffSize64 = 0; + TWO_UINT64 dataSize64 = 0; + TWO_UINT64 sampleCount64 = 0; /* nr of samples in the WAVE sense: 1 sample are all pcm samples of all channels of one time slice */ + int mustWriteRF64 = 0; + + if (!self) return __TWO_ERROR; + + /* check for 4 GB (switch to RF64) */ + if ( self->dataSize > self->dataSizeLimit ) { + /* when we exceed 4 GB: switch from std wave header to RF64 header */ + mustWriteRF64 = 1; + } + + /* calc header values */ + if (mustWriteRF64 == 0) { + /* write padding byte if dataSize is uneven */ + int pad = 0; + if (self->dataSize % 2 > 0) { + char tmp= 0x00; + fwrite(&tmp, sizeof(char), 1, self->theFile); + pad = 1; + } + riffSize_le = LittleEndian32(self->dataChunkOffset - 8 + 8 + (unsigned int)self->dataSize + pad); /* sizeof(hdr) - (8 bytes of riff chunk header) + (8 bytes data chunk header) + sizeof(raw-pcm-data) + padding Byte */ + dataSize_le = LittleEndian32((unsigned int)self->dataSize); + } else { + riffSize_le = 0xffffffff; + dataSize_le = 0xffffffff; + riffSize64 = LittleEndian64( self->dataSize + (TWO_UINT64)self->dataChunkOffset ); + dataSize64 = LittleEndian64( self->dataSize ); + sampleCount64 = LittleEndian64( self->dataSize / (TWO_UINT64)self->blockAlign ); + } + + /* now overwrite length/size values in header with the actual/real ones */ + if (mustWriteRF64 == 0) { + /* riffsize32 */ + fseek(self->theFile, 4, SEEK_SET); + fwrite(&riffSize_le, sizeof(riffSize_le), 1, self->theFile); + /* datasize32 */ + fseek(self->theFile, self->dataChunkOffset + 4, SEEK_SET); + fwrite(&dataSize_le, sizeof(dataSize_le), 1, self->theFile); + } else { + unsigned int rf64sig = BigEndian32('R','F','6','4'); + unsigned int ds64sig = BigEndian32('d','s','6','4'); + + /* replace RIFF->RF64 */ + fseek(self->theFile, 0, SEEK_SET); + fwrite(&rf64sig, sizeof(rf64sig), 1, self->theFile); + + /* riffsize32 */ + fseek(self->theFile, 4, SEEK_SET); + fwrite(&riffSize_le, sizeof(riffSize_le), 1, self->theFile); + + /* replace JUNK->ds64 */ + fseek(self->theFile, self->junkChunkOffset, SEEK_SET); + fwrite(&ds64sig, sizeof(ds64sig), 1, self->theFile); + + /* riffSize64, dataSize64, sampleCount64 */ + fseek(self->theFile, self->junkChunkOffset + 8, SEEK_SET); + fwrite(&riffSize64, sizeof(riffSize64), 1, self->theFile); + fwrite(&dataSize64, sizeof(dataSize64), 1, self->theFile); + fwrite(&sampleCount64, sizeof(sampleCount64), 1, self->theFile); + + /* datasize32 */ + fseek(self->theFile, self->dataChunkOffset + 4, SEEK_SET); + fwrite(&dataSize_le, sizeof(dataSize_le), 1, self->theFile); + } + + fclose(self->theFile); + free(self); + + return __TWO_SUCCESS; +} + +#ifdef TWO_SUPPORT_BWF +static int CloseWavBWF( + WAVEFILEOUT* self, + WAVEOUT_LOUDNESSINFO bextData + ) +{ + int wordData; + + if (!self) return __TWO_ERROR; + + if (self->bextChunkOffset) { + /* Offset for Loudness Data in bext-chunk: 8: Chunk-Header, 412:prev.Data */ + fseek(self->theFile, self->bextChunkOffset+8+412, SEEK_SET); + + wordData = LittleEndian32(EncodeLoudness(bextData.loudnessVal)); + fwrite(&wordData, 2, 1, self->theFile); + + wordData = LittleEndian32(EncodeLoudness(bextData.loudnessRange)); + fwrite(&wordData, 2, 1, self->theFile); + + wordData = LittleEndian32(EncodeLoudness(bextData.maxTruePeakLevel)); + fwrite(&wordData, 2, 1, self->theFile); + + wordData = LittleEndian32(EncodeLoudness(bextData.maxMomentaryLoudnes)); + fwrite(&wordData, 2, 1, self->theFile); + + wordData = LittleEndian32(EncodeLoudness(bextData.maxShortTermLoudness)); + fwrite(&wordData, 2, 1, self->theFile); + } + + return CloseWav(self); +} +#endif + +/*------------- local subs ----------------*/ + +static __inline unsigned int BigEndian32(char a, char b, char c, char d) +{ +#ifdef __TWO_LE + return + (unsigned int) d << 24 | + (unsigned int) c << 16 | + (unsigned int) b << 8 | + (unsigned int) a ; +#else + return + (unsigned int) a << 24 | + (unsigned int) b << 16 | + (unsigned int) c << 8 | + (unsigned int) d ; +#endif +} + + +static __inline unsigned int LittleEndian32(unsigned int v) +{ +#ifdef __TWO_LE + return v; +#else + return + (v & 0x000000FF) << 24 | + (v & 0x0000FF00) << 8 | + (v & 0x00FF0000) >> 8 | + (v & 0xFF000000) >> 24 ; +#endif +} + + +/* signed version of the above */ +static __inline unsigned int LittleEndian32s(int v) +{ +#ifdef __TWO_LE + return v; +#else + return + (v & 0x000000FF) << 24 | + (v & 0x0000FF00) << 8 | + (v & 0x00FF0000) >> 8 | + (v & 0xFF000000) >> 24 ; +#endif +} + + +static __inline short LittleEndian16(short v) +{ +#ifdef __TWO_LE + return v; +#else + return ((v << 8) & 0xFF00) | ((v >> 8) & 0x00FF); +#endif +} + +static __inline TWO_UINT64 LittleEndian64(TWO_UINT64 v) +{ +#ifdef __TWO_LE + return v; +#else + return + (v & 0x00000000000000FF) << 56 | + (v & 0x000000000000FF00) << 40 | + (v & 0x0000000000FF0000) << 24 | + (v & 0x00000000FF000000) << 8 | + (v & 0x000000FF00000000) >> 8 | + (v & 0x0000FF0000000000) >> 24 | + (v & 0x00FF000000000000) >> 40 | + (v & 0xFF00000000000000) >> 56 ; +#endif +} + +#ifdef TWO_SUPPORT_BWF +static unsigned int EncodeLoudness(float x) +{ + int s = (x>0)-(x<0); + return (int)( x*100.0f + s*0.5f ); +} +#endif + +static __inline int __dataSizeChk( WAVEFILEOUT* self, int newbytes ) +{ + if (!self) return __TWO_ERROR; + + if ( (self->dataSize + ((TWO_UINT64)newbytes) ) > self->dataSizeLimit64 ) { + return __TWO_ERROR; + } + + return __TWO_SUCCESS; +} + +#endif /* __TINYWAVEOUT_C_H__ */ + + + diff --git a/lib_lc3plus/tns_coder_fx.c b/lib_lc3plus/tns_coder_fx.c new file mode 100644 index 000000000..640e246cc --- /dev/null +++ b/lib_lc3plus/tns_coder_fx.c @@ -0,0 +1,378 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order); +static void Index2Parcor(const Word16 index[], Word16 parCoeff[], Word16 order); +static Word32 FIRLattice(Word16 order, const Word16 *parCoeff /*Q15*/, Word32 *state, Word32 x /* Q0 */); + +/*************************************************************************/ + +void processTnsCoder_fx(Word16 *bits, Word16 indexes[], Word32 x[], Word16 BW_cutoff_idx, Word16 order[], + Word16 *numfilters, Word16 enable_lpc_weighting, Word16 nSubdivisions, Word16 frame_dms, + Word16 maxLen, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif + , Word16 near_nyquist_flag +) +{ + Dyn_Mem_Deluxe_In(Word16 * tmpbuf; Word32 * rxx, epsP, *state, L_tmp, *A, predictionGain, alpha; Word16 * RC, inv; + Word16 n, n2, headroom, shift, tmp, shifts, facs, facs_e, stopfreq, xLen, maxOrder; + Word16 startfreq[TNS_NUMFILTERS_MAX]; const Word16 *subdiv_startfreq, *subdiv_stopfreq; + Counter i, j, iSubdivisions, lag; Word8 * LevinsonBuffer;); + + /* Buffer alignment */ + tmpbuf = (Word16 *)scratchAlign(scratchBuffer, 0); /* Size = 2 * MAX_LEN */ + + rxx = (Word32 *)scratchAlign(tmpbuf, sizeof(*tmpbuf) * maxLen); /* Size = 4 * (MAXLAG + 1) = 36 bytes */ + + state = (Word32 *)scratchAlign(rxx, sizeof(*rxx) * (MAXLAG + 1)); /* Size = 4 * MAXLAG = 32 bytes */ + + A = (Word32 *)scratchAlign(state, sizeof(*state) * MAXLAG); /* Size = 4 * (MAXLAG + 1) = 36 bytes */ + + RC = (Word16 *)scratchAlign(A, sizeof(*A) * (MAXLAG + 1)); /* Size = 2 * MAXLAG = 16 bytes */ + + LevinsonBuffer = (Word8 *)scratchAlign(RC, sizeof(*RC) * (MAXLAG)); /* Size = 4 * (M_LTPF + 1) = 100 bytes */ + + /* Init */ + *bits = 0; + move16(); + maxOrder = MAXLAG; + move16(); + *numfilters = 1; + move16(); + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + xLen = BW_cutoff_bin_all_HR[BW_cutoff_idx]; + } + else +#endif + { + xLen = BW_cutoff_bin_all[BW_cutoff_idx]; + } + move16(); + + SWITCH (frame_dms) + { + case 25: + startfreq[0] = 3; + move16(); + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + subdiv_startfreq = tns_subdiv_startfreq_2_5ms_HR[BW_cutoff_idx - 4]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq_2_5ms_HR[BW_cutoff_idx - 4]; + move16(); + } + else +#endif + { + subdiv_startfreq = tns_subdiv_startfreq_2_5ms[BW_cutoff_idx]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq_2_5ms[BW_cutoff_idx]; + move16(); + } + xLen = shr_pos(xLen, 2); + maxOrder = 4; + move16(); + BREAK; + case 50: + startfreq[0] = 6; + move16(); + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + subdiv_startfreq = tns_subdiv_startfreq_5ms_HR[BW_cutoff_idx - 4]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq_5ms_HR[BW_cutoff_idx - 4]; + move16(); + } + else +#endif + { + subdiv_startfreq = tns_subdiv_startfreq_5ms[BW_cutoff_idx]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq_5ms[BW_cutoff_idx]; + move16(); + } + xLen = shr_pos(xLen, 1); + maxOrder = 4; + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + startfreq[0] = 9; + move16(); + subdiv_startfreq = tns_subdiv_startfreq_7_5ms[BW_cutoff_idx]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq_7_5ms[BW_cutoff_idx]; + move16(); + tmp = shr_pos(xLen, 2); + xLen = add(tmp, add(tmp, tmp)); + maxOrder = 8; + BREAK; +#endif + default: /* 100 */ + startfreq[0] = 12; + move16(); + +#ifdef ENABLE_HR_MODE + if (hrmode) + { + subdiv_startfreq = tns_subdiv_startfreq_HR[BW_cutoff_idx - 4]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq_HR[BW_cutoff_idx - 4]; + move16(); + } + else +#endif + { + subdiv_startfreq = tns_subdiv_startfreq[BW_cutoff_idx]; + move16(); + subdiv_stopfreq = tns_subdiv_stopfreq[BW_cutoff_idx]; + move16(); + } + BREAK; + } + + IF (sub(BW_cutoff_idx, 3) >= 0 && frame_dms >= 50) + { + *numfilters = 2; + startfreq[1] = shr_pos(xLen, 1); + } + + basop_memset(state, 0, MAXLAG * sizeof(*state)); + + FOR (j = 0; j < *numfilters; j++) + { + basop_memset(rxx, 0, (maxOrder + 1) * sizeof(*rxx)); + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + n = sub(subdiv_stopfreq[nSubdivisions * j + iSubdivisions], + subdiv_startfreq[nSubdivisions * j + iSubdivisions]); + + /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/ + headroom = getScaleFactor32_lc3plus(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], n); + + /* Calculate norm of spectrum band */ + L_tmp = Norm32Norm(x + subdiv_startfreq[nSubdivisions * j + iSubdivisions], headroom, n, &shift); + + /* Rounding to avoid overflow when computing the autocorrelation below */ + tmp = sub(norm_l(L_tmp), 1); + L_tmp = L_shl(L_tmp, tmp); + shift = sub(shift, tmp); + L_tmp = L_add(L_tmp, 0x8000); + L_tmp = L_and(L_tmp, 0x7FFF0000); + + IF (L_tmp == 0) + { + rxx[0] = 0x7FFFFFFF; + move32(); + basop_memset(&rxx[1], 0, (maxOrder) * sizeof(*rxx)); + BREAK; + } + + /* get pre-shift for autocorrelation */ + tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */ + tmp = shr_pos(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */ + shifts = s_min(tmp, headroom); + + /* calc normalization factor */ + facs_e = shl_pos(sub(tmp, shifts), 1); + + SWITCH (frame_dms) + { + case 25: facs_e = add(facs_e, 1); BREAK; + case 50: facs_e = add(facs_e, 1); BREAK; +#ifdef CR8_G_ADD_75MS + case 75: BREAK; +#endif + case 100: BREAK; + } + + tmp = sub(1, shl_pos(tmp, 1)); /* exponent of autocorrelation */ + L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */ + /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */ + facs = div_s(0x2000, round_fx(L_tmp)); /* L_tmp is >= 0x2000000 */ + + FOR (i = 0; i < n; i++) + { + tmpbuf[i] = round_fx_sat(L_shl_sat(x[subdiv_startfreq[nSubdivisions * j + iSubdivisions] + i], shifts)); + move16(); + } + + FOR (lag = 0; lag <= maxOrder; lag++) + { + n2 = sub(n, lag); + L_tmp = L_deposit_l(0); + FOR (i = 0; i < n2; i++) + { + L_tmp = L_mac0(L_tmp, tmpbuf[i], tmpbuf[i + lag]); + } + if (lag != 0) + L_tmp = Mpy_32_32_lc3plus(L_tmp, tnsAcfWindow_lc3plus[lag - 1]); + + L_tmp = Mpy_32_16_lc3plus(L_tmp, facs); + L_tmp = L_shl(L_tmp, facs_e); + + rxx[lag] = L_add(rxx[lag], L_tmp); + move32(); + } + } + + /* Levinson-Durbin */ + processLevinson_fx(A, rxx, maxOrder, RC, &epsP, LevinsonBuffer); + + /* Prediction Gain */ + shift = norm_l(epsP); + inv = div_s(16383, extract_h(L_shl_pos(epsP, shift))); + predictionGain = Mpy_32_32_lc3plus(rxx[0], Mpy_32_16_lc3plus(L_sub(MAX_32, Mpy_32_16_lc3plus(L_shl(epsP, shift), inv)), inv)); + + IF (L_sub(predictionGain, L_shr_pos_pos(0x30000000, shift)) > 0 && near_nyquist_flag == 0) + { + /* If Prediction Gain is low */ + test(); + IF (enable_lpc_weighting != 0 && L_sub(predictionGain, L_shr_pos_pos(0x40000000, shift)) < 0) + { + /* LPC weighting */ + alpha = L_add(0x6CCCCCCD, + Mpy_32_32_lc3plus(0x13333333, L_shl_pos(L_sub(L_shl_pos(predictionGain, shift), 0x30000000), 3))); + L_tmp = alpha; + FOR (i = 1; i < maxOrder; i++) + { + A[i] = Mpy_32_32_lc3plus(A[i], L_tmp); + move32(); + L_tmp = Mpy_32_32_lc3plus(L_tmp, alpha); + } + A[maxOrder] = Mpy_32_32_lc3plus(A[maxOrder], L_tmp); + move32(); + + /* LPC -> RC */ + lpc2rc(A, RC, maxOrder); + } + + /* Reflection Coefficients Quantization */ + Parcor2Index(RC, &indexes[MAXLAG * j], maxOrder); + + /* reduce filter order by truncating trailing zeros */ + i = sub(maxOrder, 1); + WHILE ((i >= 0) && (indexes[MAXLAG * j + i] == INDEX_SHIFT)) + { + i = sub(i, 1); + } + order[j] = add(i, 1); + + // Disable TNS if order is 0: + IF (order[j] == 0) { + // Jump to else statement + goto tns_disabled; + } + /* Count bits */ + L_tmp = L_deposit_l(ac_tns_order_bits[enable_lpc_weighting][order[j] - 1]); + FOR (i = 0; i < order[j]; i++) + { + L_tmp = L_add(L_tmp, L_deposit_l(ac_tns_coef_bits[i][indexes[MAXLAG * j + i]])); + } + *bits = add(*bits, add(2, extract_l(L_shr_pos(L_sub(L_tmp, 1), 11)))); + move16(); + + /* Unquantize Reflection Coefficients */ + Index2Parcor(&indexes[MAXLAG * j], RC, order[j]); + + /* Stop frequency */ + stopfreq = xLen; + move16(); + IF (sub(*numfilters, 2) == 0 && j == 0) + { + stopfreq = startfreq[1]; + } + + /* Filter */ + FOR (i = startfreq[j]; i < stopfreq; i++) + { + x[i] = FIRLattice(order[j], RC, state, x[i]); + move32(); + } + } + ELSE + { +tns_disabled: + /* TNS disabled */ + *bits = add(*bits, 1); + order[j] = 0; + } + } + + Dyn_Mem_Deluxe_Out(); +} + +/*************************************************************************/ + +static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order) +{ + Dyn_Mem_Deluxe_In(Counter i; Word16 iIndex; Word16 x;); + + FOR (i = 0; i < order; i++) + { + move16(); + move16(); + iIndex = 1; + x = parCoeff[i]; + + WHILE ((iIndex < TNS_COEF_RES) && (x > tnsQuantThr[iIndex - 1])) + { + iIndex = add(iIndex, 1); + } + index[i] = sub(iIndex, 1); + move16(); + } + + Dyn_Mem_Deluxe_Out(); +} + +static void Index2Parcor(const Word16 index[], Word16 parCoeff[], Word16 order) +{ + Counter i; + FOR (i = 0; i < order; i++) + { + parCoeff[i] = tnsQuantPts[index[i]]; + move16(); + } +} + +static Word32 FIRLattice(Word16 order, const Word16 *parCoeff /*Q15*/, Word32 *state, Word32 x /* Q0 */) +{ + Dyn_Mem_Deluxe_In(Counter i; Word32 tmpSave, tmp;); + + tmpSave = L_add(x, 0); + + FOR (i = 0; i < order - 1; i++) + { + tmp = L_add(state[i], Mpy_32_16_lc3plus(x, parCoeff[i])); + x = L_add(x, Mpy_32_16_lc3plus(state[i], parCoeff[i])); /* exponent: 31+0 */ + state[i] = tmpSave; + move32(); + tmpSave = L_add(tmp, 0); + } + + /* last stage: only need half operations */ + x = L_add(x, Mpy_32_16_lc3plus(state[order - 1], parCoeff[order - 1])); + state[order - 1] = tmpSave; + move32(); + Dyn_Mem_Deluxe_Out(); + return x; +} + diff --git a/lib_lc3plus/tns_decoder_fx.c b/lib_lc3plus/tns_decoder_fx.c new file mode 100644 index 000000000..b138c4510 --- /dev/null +++ b/lib_lc3plus/tns_decoder_fx.c @@ -0,0 +1,150 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.4.5 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "functions.h" + +static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x); + +/*************************************************************************/ + +void processTnsDecoder_fx(Word16 rc_idx[], Word32 x[], Word16 xLen, Word16 order[], Word16 *x_e, Word16 BW_stopband_idx, + Word16 frame_dms, Word8 *scratchBuffer +#ifdef ENABLE_HR_MODE + , Word16 hrmode +#endif +) +{ + Dyn_Mem_Deluxe_In( + Word32 *state; + Counter i, j; + Word16 s1, s2, s, *rc, f, stopfreq, BW_stopband; + Word16 numfilters, startfreq[TNS_NUMFILTERS_MAX]; + ); + + state = (Word32 *)scratchAlign(scratchBuffer, 0); /* Size = MAXLAG */ + rc = (Word16 *)scratchAlign(state, sizeof(*state) * MAXLAG); /* Size = MAXLAG */ + + numfilters = 1; + +#ifdef ENABLE_HR_MODE + if (hrmode == 1) + { + BW_stopband = BW_cutoff_bin_all_HR[BW_stopband_idx]; move16(); + } + else +#endif + { + BW_stopband = BW_cutoff_bin_all[BW_stopband_idx]; move16(); + } + + SWITCH (frame_dms) + { + case 25: + startfreq[0] = 3; move16(); + BW_stopband = shr_pos(BW_stopband, 2); + BREAK; + case 50: + startfreq[0] = 6; move16(); + BW_stopband = shr_pos(BW_stopband, 1); + BREAK; +#ifdef CR8_G_ADD_75MS + case 75: + startfreq[0] = 9; move16(); + BW_stopband = add(shr_pos(BW_stopband, 2), add(shr_pos(BW_stopband, 2), shr_pos(BW_stopband, 2))); + BREAK; +#endif + case 100: startfreq[0] = 12; BREAK; + } + + IF (sub(BW_stopband_idx, 3) >= 0 && frame_dms >= 50) + { + numfilters = 2; + startfreq[1] = shr_pos(BW_stopband, 1); + } + stopfreq = 0; + + test(); test(); + IF (order[0] > 0 || (sub(numfilters, 2) == 0 && order[1] > 0)) + { + /* Scaling */ + f = startfreq[0]; move16(); + test(); + IF (sub(numfilters, 2) == 0 && order[0] == 0) + { + f = startfreq[1]; move16(); + } + s1 = getScaleFactor32_lc3plus(x, f); + s2 = getScaleFactor32_lc3plus(x + f, sub(xLen, f)); + s = s_min(s1, sub(s2, 7)); /* 7 bits of headroom for IIR filtering */ + *x_e = sub(*x_e, s); + +/* Init Filter */ + basop_memset(state, 0, MAXLAG * sizeof(Word32)); + FOR (i = 0; i < f; i++) + { + x[i] = L_shl(x[i], s); move32(); + } + + FOR (j = 0; j < numfilters; j++) + { + IF (order[j] > 0) + { + /* Unquantize coefficients */ + FOR (i = 0; i < order[j]; i++) + { + rc[i] = tnsQuantPts[rc_idx[j * MAXLAG + i]]; move16(); + } + + /* Stop frequency */ + stopfreq = BW_stopband; move16(); + IF (sub(numfilters, 2) == 0 && j == 0) + { + stopfreq = startfreq[1]; + } + + /* Filter */ + FOR (i = startfreq[j]; i < stopfreq; i++) + { + x[i] = IIRLattice(order[j], rc, state, L_shl(x[i], s)); move32(); + } + } + } + FOR (i = stopfreq; i < xLen; i++) + { + x[i] = L_shl(x[i], s); move32(); + } + } + Dyn_Mem_Deluxe_Out(); +} + +/*************************************************************************/ +/*************************************************************************/ +/*************************************************************************/ + +static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x) +{ + Dyn_Mem_Deluxe_In( + Counter i; + ); + + /* first stage: no need to calculate state[order-1] */ + x = L_sub_sat(x, Mpy_32_16_lc3plus(state[order - 1], parCoeff[order - 1])); + + FOR (i = order - 2; i >= 0; i--) + { + x = L_sub(x, Mpy_32_16_lc3plus(state[i], parCoeff[i])); + state[i + 1] = L_add(state[i], Mpy_32_16_lc3plus(x, parCoeff[i])); move32(); + } + + state[0] = x; move32(); + + Dyn_Mem_Deluxe_Out(); + return x; +} + diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 4afd38886..4a62de19f 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -89,52 +89,6 @@ ivas_error get_channel_config( #endif -/*----------------------------------------------------------------------------------* - * Limiter prototypes - *----------------------------------------------------------------------------------*/ - - -ivas_error ivas_limiter_open( - IVAS_LIMITER_HANDLE *hLimiter_out, /* o : limiter struct handle */ - const int16_t num_channels, /* i : number of I/O channels */ - const int32_t sampling_rate /* i : sampling rate for processing */ -); - -void ivas_limiter_close( - IVAS_LIMITER_HANDLE* phLimiter /* i/o: pointer to limiter handle, can be NULL */ -); - -void ivas_limiter_dec -( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - float *output[MAX_OUTPUT_CHANNELS], /* i/o: input/output buffer */ - const int16_t num_channels, /* i : number of channels to be processed */ - const int16_t output_frame, /* i : number of samples per channel in the buffer */ - const int16_t BER_detect /* i : BER detect flag */ -); -void ivas_limiter_dec_fx( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - Word32 *output[MAX_OUTPUT_CHANNELS], /* i/o: input/output buffer */ - const Word16 num_channels, /* i : number of channels to be processed */ - const Word16 output_frame, /* i : number of samples per channel in the buffer */ - const Word16 BER_detect, /* i : BER detect flag */ - Word16 q_factor /* i : Q factor of the output samples */ -); -void limiter_process( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - const int16_t output_frame, /* i : number of samples to be processed per channel in the I/O buffer */ - const float threshold, /* i : signal amplitude above which limiting starts to be applied */ - const int16_t BER_detect, /* i : BER detect flag */ - int16_t *strong_saturation_cnt /* i/o: counter of strong saturations (can be NULL) */ -); -void limiter_process_fx( - IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle */ - const Word16 output_frame, /* i : number of samples to be processed per channel in the I/O buffer */ - const Word32 threshold, /* i : signal amplitude above which limiting starts to be applied */ - const Word16 BER_detect, /* i : BER detect flag */ - Word16 *strong_saturation_cnt, /* i/o: counter of strong saturations (can be NULL) */ - Word16 q_factor /* i : Q factor of output samples */ -); /*----------------------------------------------------------------------------------* * TD decorr. function prototypes *----------------------------------------------------------------------------------*/ @@ -1620,26 +1574,6 @@ void ivas_headTrack_close_fx( HEAD_TRACK_DATA_HANDLE *hHeadTrackData /* i/o: head track handle */ ); -void Euler2Quat( - const float yaw, /* i : yaw (x) */ - const float pitch, /* i : pitch (y) */ - const float roll, /* i : roll (z) */ - IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ -); -void Euler2Quat_fx( - const Word32 yaw, /* i : yaw (x) Q22 */ - const Word32 pitch, /* i : pitch (y) Q22 */ - const Word32 roll, /* i : roll (z) Q22 */ - IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ -); -float deg2rad( - float degrees -); - -Word32 deg2rad_fx( - Word32 degrees -); - float rad2deg( float radians ); diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 758d787b1..8b938a7e0 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -239,53 +239,6 @@ void QuatToRotMat_fx( } -void Euler2Quat_fx( - const Word32 yaw, /* i : yaw (x) Q22 */ - const Word32 pitch, /* i : pitch (y) Q22 */ - const Word32 roll, /* i : roll (z) Q22 */ - IVAS_QUATERNION *quat /* o : quaternion describing the rotation Q19 */ -) -{ - Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) ); // Q14 - Word16 sr = getSinWord16( extract_l( L_shr_r( roll, 10 ) ) ); - Word16 cp = getCosWord16( extract_l( L_shr_r( pitch, 10 ) ) ); - Word16 sp = getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ); - Word16 cy = getCosWord16( extract_l( L_shr_r( yaw, 10 ) ) ); - Word16 sy = getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ); - quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); // Q19 - move32(); - quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); // Q19 - move32(); - quat->y_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( sr, cp ), sy ), Mpy_32_16_1( L_mult0( cr, sp ), cy ) ), 5 ); // Q19 - move32(); - quat->z_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( cr, cp ), sy ), Mpy_32_16_1( L_mult0( sr, sp ), cy ) ), 5 ); // Q19 - move32(); - - return; -} - - -/*------------------------------------------------------------------------- - * deg2rad() - * - * Converts degrees to normalized radians - *------------------------------------------------------------------------*/ -Word32 deg2rad_fx( - Word32 degrees // Q23 -) -{ - WHILE( GE_32( degrees, DEGREE_180 ) ) - { - degrees = L_sub( degrees, DEGREE_360 ); - } - WHILE( LE_32( degrees, -DEGREE_180 ) ) - { - degrees = L_add( degrees, DEGREE_360 ); - } - - return Mpy_32_32( PI_OVER_180_FX, degrees ); // Q23 -} - /*------------------------------------------------------------------------- * rad2deg() * diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 38b2fe524..15381d5bd 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -664,9 +664,16 @@ typedef struct ivas_binaural_rendering_conv_module_struct_fx Word32 ***filterTapsRightReal_fx; Word32 ***filterTapsRightImag_fx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 ****filterStatesLeftReal_fx; + Word32 ****filterStatesLeftImag_fx; + Word16 ****Q_filterStatesLeft; +#else Word32 ***filterStatesLeftReal_fx; Word32 ***filterStatesLeftImag_fx; Word16 ***Q_filterStatesLeft; +#endif + Word16 numTapsArray[BINAURAL_CONVBANDS]; Word16 numTaps; diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 74e6070b5..5af21427f 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -55,20 +55,6 @@ typedef float IVAS_REND_LfePanMtx[RENDERER_MAX_INPUT_LFE_CHANNELS][IVAS_MAX_OUTPUT_CHANNELS]; typedef Word32 IVAS_REND_LfePanMtx_fx[RENDERER_MAX_INPUT_LFE_CHANNELS][IVAS_MAX_OUTPUT_CHANNELS]; -typedef struct -{ - Word16 numSamplesPerChannel; - Word16 numChannels; -} IVAS_REND_AudioBufferConfig; -typedef struct -{ - IVAS_REND_AudioBufferConfig config; - Word16 q_factor; - Word16 *pq_fact; - Word32 *data_fx; - // Word16 Q_data; -} IVAS_REND_AudioBuffer; - typedef struct { -- GitLab From 2f2d6f6db7dceb68f322c640a53285cbbe4d954d Mon Sep 17 00:00:00 2001 From: rtyag Date: Tue, 28 Jan 2025 17:23:03 +1100 Subject: [PATCH 02/43] MSVS changes, not compiling yet --- Makefile | 92 +++-- Workspace_msvc/Workspace_msvc.sln | 6 + Workspace_msvc/decoder.vcxproj | 7 +- Workspace_msvc/lib_com.vcxproj | 8 +- Workspace_msvc/lib_dec.vcxproj | 4 +- Workspace_msvc/lib_enc.vcxproj | 4 +- Workspace_msvc/lib_rend.vcxproj | 9 +- Workspace_msvc/lib_util.vcxproj | 8 +- Workspace_msvc/renderer.vcxproj | 7 +- lib_com/common_api_types.h | 2 +- lib_com/ivas_rotation_com.c | 3 - lib_dec/ivas_binRenderer_internal.c | 473 +++++++++++++++++++++++- lib_isar/isar_stat.h | 2 +- lib_rend/ivas_stat_rend.h | 28 ++ lib_util/split_rend_bfi_file_reader.c | 162 ++++++++ lib_util/split_rend_bfi_file_reader.h | 60 +++ lib_util/split_render_file_read_write.c | 431 +++++++++++++++++++++ lib_util/split_render_file_read_write.h | 99 +++++ 18 files changed, 1348 insertions(+), 57 deletions(-) create mode 100644 lib_util/split_rend_bfi_file_reader.c create mode 100644 lib_util/split_rend_bfi_file_reader.h create mode 100644 lib_util/split_render_file_read_write.c create mode 100644 lib_util/split_render_file_read_write.h diff --git a/Makefile b/Makefile index 4e92bc951..92d3cd3f0 100644 --- a/Makefile +++ b/Makefile @@ -7,23 +7,31 @@ SRC_LIBDEBUG = lib_debug SRC_LIBDEC = lib_dec SRC_LIBENC = lib_enc SRC_LIBREND = lib_rend +SRC_LIBISAR = lib_isar +SRC_LC3PLUS = lib_lc3plus lib_lc3plus/fft SRC_LIBUTIL = lib_util SRC_APP = apps BUILD = build OBJDIR = obj -SRC_DIRS = $(sort -u $(SRC_LIBCOM) $(SRC_LIBDEBUG) $(SRC_LIBDEC) $(SRC_LIBENC) $(SRC_LIBREND) $(SRC_LIBUTIL) $(SRC_APP)) +INCLUDE_SPLIT = 1 + +SRC_DIRS = $(sort -u $(SRC_LIBCOM) $(SRC_LIBDEBUG) $(SRC_LIBDEC) $(SRC_LIBENC) $(SRC_LIBREND) $(SRC_LIBISAR) $(SRC_LC3PLUS) $(SRC_LIBUTIL) $(SRC_APP)) # Name of CLI binaries -CLI_APIDEC ?= IVAS_dec -CLI_APIENC ?= IVAS_cod -CLI_APIREND ?= IVAS_rend -LIB_LIBCOM ?= libivascom.a -LIB_LIBDEBUG ?= libivasdebug.a -LIB_LIBDEC ?= libivasdec.a -LIB_LIBENC ?= libivasenc.a -LIB_LIBREND ?= libivasrend.a -LIB_LIBUTIL ?= libivasutil.a +CLI_APIDEC ?= IVAS_dec +CLI_APIENC ?= IVAS_cod +CLI_APIREND ?= IVAS_rend +CLI_APIPOSTREND ?= ISAR_post_rend +LIB_LIBCOM ?= libivascom.a +LIB_LIBDEBUG ?= libivasdebug.a +LIB_LIBDEC ?= libivasdec.a +LIB_LIBENC ?= libivasenc.a +LIB_LIBREND ?= libivasrend.a +LIB_LIBISAR ?= libisar.a +LIB_LC3PLUS ?= liblc3plus.a +LIB_LIBUTIL ?= libivasutil.a + # Default tool settings CC ?= gcc @@ -124,8 +132,14 @@ CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR)) # Source file search paths VPATH = $(SRC_DIRS) -# Filter out files that are not part of the build -EXCLUDED_FILES = +# Split rendering files +SRCS_SPLIT_REND = ivas_CQMFDecoder.c ivas_CQMFEncoder.c ivas_PerceptualModel.c ivas_PredDecoder.c \ + ivas_PredEncoder.c ivas_RMSEnvGrouping.c ivas_MSPred.c ivas_NoiseGen.c \ + ivas_splitRend_lcld_dec.c ivas_splitRend_lcld_enc.c \ + ivas_splitRendererPLC.c ivas_splitRendererPost.c ivas_splitRendererPre.c \ + ivas_splitRenderer_utils.c split_rend_bfi_file_reader.c split_render_file_read_write.c \ + ivas_lcld_tables.c + ############################################################################### @@ -135,27 +149,36 @@ SRCS_LIBDEC = $(foreach DIR,$(SRC_LIBDEC),$(patsubst $(DIR)/%,%,$(wildcard $(D SRCS_LIBENC = $(foreach DIR,$(SRC_LIBENC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) SRCS_LIBREND = $(foreach DIR,$(SRC_LIBREND),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) SRCS_LIBUTIL = $(foreach DIR,$(SRC_LIBUTIL),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) - -SRCS_LIBENC := $(filter-out $(EXCLUDED_FILES),$(SRCS_LIBENC)) +SRCS_LIBISAR = $(foreach DIR,$(SRC_LIBISAR),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) +ifeq "$(INCLUDE_SPLIT)" "1" +SRCS_LC3PLUS = $(foreach DIR,$(SRC_LC3PLUS),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) +else +# SRCS_LIBREND := $(filter-out $(SRCS_SPLIT_REND),$(SRCS_LIBREND)) +# SRCS_LIBUTIL := $(filter-out $(SRCS_SPLIT_REND),$(SRCS_LIBUTIL)) +endif OBJS_LIBCOM = $(addprefix $(OBJDIR)/,$(SRCS_LIBCOM:.c=.o)) OBJS_LIBDEBUG = $(addprefix $(OBJDIR)/,$(SRCS_LIBDEBUG:.c=.o)) OBJS_LIBDEC = $(addprefix $(OBJDIR)/,$(SRCS_LIBDEC:.c=.o)) OBJS_LIBENC = $(addprefix $(OBJDIR)/,$(SRCS_LIBENC:.c=.o)) OBJS_LIBREND = $(addprefix $(OBJDIR)/,$(SRCS_LIBREND:.c=.o)) +OBJS_LIBISAR = $(addprefix $(OBJDIR)/,$(SRCS_LIBISAR:.c=.o)) +OBJS_LC3PLUS = $(addprefix $(OBJDIR)/,$(SRCS_LC3PLUS:.c=.o)) OBJS_LIBUTIL = $(addprefix $(OBJDIR)/,$(SRCS_LIBUTIL:.c=.o)) OBJS_CLI_APIDEC = $(OBJDIR)/decoder.o OBJS_CLI_APIENC = $(OBJDIR)/encoder.o OBJS_CLI_APPREND = $(OBJDIR)/renderer.o +OBJS_CLI_APPPOSTREND = $(OBJDIR)/isar_post_rend.o DEPS = $(addprefix $(OBJDIR)/,$(SRCS_LIBCOM:.c=.P) $(SRCS_LIBDEBUG:.c=.P) $(SRCS_LIBDEC:.c=.P) \ - $(SRCS_LIBENC:.c=.P) $(SRCS_LIBUTIL:.c=.P) $(SRCS_LIBREND:.c=.P)) + $(SRCS_LIBENC:.c=.P) $(SRCS_LIBUTIL:.c=.P) $(SRCS_LIBREND:.c=.P) $(SRCS_LIBISAR:.c=.P) \ + $(SRCS_LC3PLUS:.c=.P)) ############################################################################### .PHONY: all clean -all: $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) +all: $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(CLI_APIPOSTREND) $(OBJDIR): $(QUIET)mkdir -p $(OBJDIR) @@ -163,37 +186,60 @@ $(OBJDIR): $(LIB_LIBCOM): $(OBJS_LIBCOM) $(QUIET_AR)$(AR) rcs $@ $^ -$(LIB_LIBDEC): $(OBJS_LIBDEC) $(OBJS_LIBREND) +$(LIB_LIBDEC): $(OBJS_LIBDEC) $(OBJS_LIBREND) $(OBJS_LIBISAR) $(QUIET_AR)$(AR) rcs $@ $^ $(LIB_LIBDEBUG): $(OBJS_LIBDEBUG) $(QUIET_AR)$(AR) rcs $@ $^ +$(LIB_LIBISAR): $(OBJS_LIBISAR) + $(QUIET_AR)$(AR) rcs $@ $^ + $(LIB_LIBENC): $(OBJS_LIBENC) $(QUIET_AR)$(AR) rcs $@ $^ -$(LIB_LIBREND): $(OBJS_LIBREND) +$(LIB_LIBREND): $(OBJS_LIBREND) $(OBJS_LIBISAR) + $(QUIET_AR)$(AR) rcs $@ $^ + +$(LIB_LC3PLUS): $(OBJS_LC3PLUS) +ifeq "$(INCLUDE_SPLIT)" "1" $(QUIET_AR)$(AR) rcs $@ $^ +else + +endif # Dependency on OBJS_LIBCOM added temporarily for unit-test to work $(LIB_LIBUTIL): $(OBJS_LIBUTIL) $(OBJS_LIBCOM) $(QUIET_AR)$(AR) rcs $@ $^ -$(CLI_APIENC): $(OBJS_CLI_APIENC) $(LIB_LIBENC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) +$(CLI_APIENC): $(OBJS_CLI_APIENC) $(LIB_LIBENC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIENC) -L. -livasenc -livascom -livasutil -livasdebug $(LDLIBS) -o $(CLI_APIENC) -$(CLI_APIDEC): $(OBJS_CLI_APIDEC) $(LIB_LIBDEC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) +$(CLI_APIDEC): $(OBJS_CLI_APIDEC) $(LIB_LIBDEC) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) $(LIB_LIBISAR) +ifeq "$(INCLUDE_SPLIT)" "1" + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIDEC) -L. -livasdec -livascom -livasutil -livasdebug -llc3plus $(LDLIBS) -o $(CLI_APIDEC) +else $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APIDEC) -L. -livasdec -livascom -livasutil -livasdebug $(LDLIBS) -o $(CLI_APIDEC) +endif -$(CLI_APIREND): $(OBJS_CLI_APPREND) $(LIB_LIBREND) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LIBDEC) +$(CLI_APIREND): $(OBJS_CLI_APPREND) $(LIB_LIBREND) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LIBDEC) $(LIB_LC3PLUS) $(LIB_LIBISAR) +ifeq "$(INCLUDE_SPLIT)" "1" + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APPREND) -L. -livasrend -lisar -livasdec -livasutil -livasdebug -livascom -llc3plus $(LDLIBS) -o $(CLI_APIREND) +else $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APPREND) -L. -livasrend -livasdec -livasutil -livasdebug -livascom $(LDLIBS) -o $(CLI_APIREND) +endif + +$(CLI_APIPOSTREND): $(OBJS_CLI_APPPOSTREND) $(LIB_LIBISAR) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) +ifeq "$(INCLUDE_SPLIT)" "1" + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APPPOSTREND) -L. -lisar -livasutil -livasdebug -llc3plus -livascom $(LDLIBS) -o $(CLI_APIPOSTREND) +endif -libs: $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBREND) $(LIB_LIBUTIL) +libs: $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBREND) $(LIB_LIBISAR) $(LIB_LC3PLUS) $(LIB_LIBUTIL) clean: $(QUIET)$(RM) $(OBJS_LIBENC) $(OBJS_LIBDEC) $(DEPS) $(QUIET)$(RM) $(DEPS:.P=.d) $(QUIET)test ! -d $(OBJDIR) || rm -rf $(OBJDIR) - $(QUIET)$(RM) $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) $(LIB_LIBREND) + $(QUIET)$(RM) $(CLI_APIENC) $(CLI_APIDEC) $(CLI_APIREND) $(CLI_APIPOSTREND) $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBUTIL) $(LIB_LIBREND) $(LIB_LIBISAR) $(LIB_LC3PLUS) $(OBJDIR)/%.o : %.c | $(OBJDIR) $(QUIET_CC)$(CC) $(CFLAGS) -c -MD -o $@ $< diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln index a0783ddbf..5449368aa 100644 --- a/Workspace_msvc/Workspace_msvc.sln +++ b/Workspace_msvc/Workspace_msvc.sln @@ -20,11 +20,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "encoder", "encoder.vcxproj" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "renderer", "renderer.vcxproj", "{12B4C8A5-1E06-4E30-B443-D1F916F52B47}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_lc3plus", "lib_lc3plus.vcxproj", "{95030B82-70CD-4C6B-84D4-61096035BEA2}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{51160D4C-55C9-4C16-A792-D94507225746}" ProjectSection(SolutionItems) = preProject ..\.clang-format = ..\.clang-format EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_isar", "lib_isar.vcxproj", "{869A305E-D99E-4C3A-BDB3-AA57ABCCE619}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "isar_post_rend", "isar_post_rend.vcxproj", "{12374ADC-0E5C-4FDD-B903-71D572413831}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 diff --git a/Workspace_msvc/decoder.vcxproj b/Workspace_msvc/decoder.vcxproj index ca0d96f44..3ab058c29 100644 --- a/Workspace_msvc/decoder.vcxproj +++ b/Workspace_msvc/decoder.vcxproj @@ -68,7 +68,7 @@ Disabled - ..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) + ..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;..\lib_isar;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) EnableFastChecks @@ -112,7 +112,7 @@ Neither false false - ..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;%(AdditionalIncludeDirectories) + ..\lib_dec;..\lib_com;..\lib_util;..\lib_debug;..\lib_isar;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true @@ -157,6 +157,9 @@ {e822ddaf-0f5f-4cd0-a694-38ae69de74d3} false + + {869a305e-d99e-4c3a-bdb3-aa57abcce619} + {2fa8f384-0775-f3b7-f8c3-85209222fc70} false diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj index 9182dd362..130a4a51d 100644 --- a/Workspace_msvc/lib_com.vcxproj +++ b/Workspace_msvc/lib_com.vcxproj @@ -59,8 +59,8 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + ..\lib_isar;..\lib_lc3plus;..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions); EnableFastChecks MultiThreadedDebug @@ -94,7 +94,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) + ..\lib_isar;..\lib_lc3plus;..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true @@ -236,6 +236,8 @@ + + diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index d6e4a7c67..dd06dabb7 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -68,7 +68,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -108,7 +108,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) true diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj index 1a706cfeb..c4862738c 100644 --- a/Workspace_msvc/lib_enc.vcxproj +++ b/Workspace_msvc/lib_enc.vcxproj @@ -68,7 +68,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -111,7 +111,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index fa11b23be..5b50ade13 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -68,7 +68,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) EnableFastChecks @@ -108,7 +108,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) true @@ -148,7 +148,6 @@ - @@ -196,6 +195,10 @@ {54509728-928b-44d9-a118-a6f92f08b34f} false + + {95030B82-70CD-4C6B-84D4-61096035BEA2} + false + diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index 86730b859..ceb342b21 100644 --- a/Workspace_msvc/lib_util.vcxproj +++ b/Workspace_msvc/lib_util.vcxproj @@ -55,7 +55,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;.%(AdditionalIncludeDirectories) + ..\lib_isar;..\lib_lc3plus;..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);ZLIB_WINAPI;%(PreprocessorDefinitions) false @@ -78,7 +78,7 @@ AnySuitable false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;.%(AdditionalIncludeDirectories) + ..\lib_isar;..\lib_lc3plus;..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_util;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);ZLIB_WINAPI;%(PreprocessorDefinitions) true @@ -120,6 +120,8 @@ + + @@ -145,6 +147,8 @@ + + diff --git a/Workspace_msvc/renderer.vcxproj b/Workspace_msvc/renderer.vcxproj index 1f95040e1..663e1df3b 100644 --- a/Workspace_msvc/renderer.vcxproj +++ b/Workspace_msvc/renderer.vcxproj @@ -65,7 +65,7 @@ Disabled - ..\lib_com;..\lib_debug;..\lib_util;..\lib_rend;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_util;..\lib_isar;..\lib_rend;..\lib_lc3plus;..\lib_dec;..\lib_enc;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;WIN32;$(Macros);%(PreprocessorDefinitions) EnableFastChecks @@ -109,7 +109,7 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_util;..\lib_rend;.%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_util;..\lib_isar;..\lib_rend;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);%(PreprocessorDefinitions) true @@ -156,6 +156,9 @@ {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3} false + + {869a305e-d99e-4c3a-bdb3-aa57abcce619} + {2FA8F384-0775-F3B7-F8C3-85209222FC70} false diff --git a/lib_com/common_api_types.h b/lib_com/common_api_types.h index 894b940b7..66aeb1721 100644 --- a/lib_com/common_api_types.h +++ b/lib_com/common_api_types.h @@ -142,7 +142,7 @@ typedef struct _IVAS_ISM_METADATA typedef struct { - float w, x, y, z; + // float w, x, y, z; Word32 w_fx, x_fx, y_fx, z_fx; Word16 q_fact; diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index d50eb4304..20eaf6188 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -42,8 +42,6 @@ #include "debug.h" #endif #include "wmc_auto.h" -#include "prot_fx2.h" -#include "basop_mpy.h" #include "basop_util.h" #include "enh64.h" /*------------------------------------------------------------------------- @@ -253,7 +251,6 @@ Word32 deg2rad_fx( return Mpy_32_32( PI_OVER_180_FX, degrees ); // Q23 } -} float deg2rad( float degrees ) { diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index bc31e32e8..913b7c366 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -490,9 +490,11 @@ static ivas_error ivas_binRenderer_convModuleOpen( IF( EQ_16( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) { /* set the memories to zero */ +#ifndef SPLIT_REND_WITH_HEAD_ROT set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); set16_fx( hBinRenConvModule->Q_filterStatesLeft[bandIdx][chIdx], 31, hBinRenConvModule->numTapsArray[bandIdx] ); +#endif IF( isLoudspeaker ) { hBinRenConvModule->filterTapsLeftReal_fx[bandIdx][chIdx] = hHrtf->leftBRIRReal_fx[bandIdx][tmp]; @@ -503,10 +505,12 @@ static ivas_error ivas_binRenderer_convModuleOpen( } ELSE { +#ifndef SPLIT_REND_WITH_HEAD_ROT /* set the memories to zero */ set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[bandIdx][chIdx], 0, hBinRenConvModule->numTaps ); set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[bandIdx][chIdx], 0, hBinRenConvModule->numTaps ); set16_fx( hBinRenConvModule->Q_filterStatesLeft[bandIdx][chIdx], 31, hBinRenConvModule->numTaps ); +#endif IF( isLoudspeaker ) { hBinRenConvModule->filterTapsLeftReal_fx[bandIdx][chIdx] = hHrtf->leftHRIRReal_fx[bandIdx][tmp]; @@ -549,6 +553,21 @@ static ivas_error ivas_binRenderer_convModuleOpen( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) + { + for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) + { + /* set the memories to zero */ + set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); + set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); + set16_fx( hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx][chIdx], 31, hBinRenConvModule->numTaps ); + } + } + } +#endif hBinRenderer->hBinRenConvModule = hBinRenConvModule; @@ -1100,6 +1119,112 @@ static void ivas_binaural_obtain_DMX_fx( return; } + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*------------------------------------------------------------------------- + * ivas_rend_openCldfbRend() + * + * Allocate and initialize CLDFB fast conv renderer handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_rend_openCldfbRend( + CLDFB_REND_WRAPPER *pCldfbRend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word32 output_Fs ) +{ + BINAURAL_RENDERER_HANDLE hBinRenderer; + Word16 convBand; + ivas_error error; + + error = IVAS_ERR_OK; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + if ( ( hBinRenderer = (BINAURAL_RENDERER_HANDLE) malloc( sizeof( BINAURAL_RENDERER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Binaural Renderer\n" ) ); + } + + if ( ( hBinRenderer->hInputSetup = (IVAS_OUTPUT_SETUP_HANDLE) malloc( sizeof( IVAS_OUTPUT_SETUP ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for output setup Binaural Renderer\n" ) ); + } + + hBinRenderer->rotInCldfb = 1; + hBinRenderer->ivas_format = SBA_FORMAT; + + hBinRenderer->max_band = extract_l( Mpy_32_32( Mpy_32_32( BINAURAL_MAXBANDS_Q25, L_shl( output_Fs, Q6 ) ), ONE_BY_48000_Q31 ) ); + move16(); + + convBand = hBinRenderer->max_band; + move16(); + + hBinRenderer->timeSlots = MAX_PARAM_SPATIAL_SUBFRAMES; /* Corresponds to 5 msec sound to motion latency */ + move16(); + + IF( GT_16( convBand, BINAURAL_CONVBANDS ) ) + { + hBinRenderer->conv_band = BINAURAL_CONVBANDS; + move16(); + } + ELSE + { + hBinRenderer->conv_band = convBand; + move16(); + } + + hBinRenderer->hInputSetup->is_loudspeaker_setup = 0; + hBinRenderer->hInputSetup->output_config = inConfig; + IF( ( error = getAudioConfigNumChannels( inConfig, &hBinRenderer->hInputSetup->nchan_out_woLFE ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + hBinRenderer->numPoses = pMultiBinPoseData->num_poses; + move16(); + } + ELSE + { + hBinRenderer->numPoses = 1; + move16(); + } + + /*LFE rendering switched off by default*/ + hBinRenderer->render_lfe = 0; + move16(); + + + /* Load HRTF tables */ + IF( NE_32( ( error = ivas_binaural_hrtf_open_fx( &pCldfbRend->hHrtfFastConv, hBinRenderer->hInputSetup->output_config, RENDERER_BINAURAL_FASTCONV ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* Allocate memories and buffers needed for convolutional module in CICP19 */ + IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, RENDERER_BINAURAL_FASTCONV, 1, inConfig, pCldfbRend->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) ) + { + return error; + } + + pCldfbRend->binaural_latency_ns = (Word32) ( pCldfbRend->hHrtfFastConv->FASTCONV_HOA3_latency_s_fx * 1000000000 ); + move32(); + hBinRenderer->hReverb = NULL; + move32(); + hBinRenderer->hEFAPdata = NULL; + move32(); + pCldfbRend->hCldfbRend = hBinRenderer; + move32(); + + return error; +} +#endif + /*------------------------------------------------------------------------- * ivas_binRenderer_open() * @@ -1137,6 +1262,18 @@ ivas_error ivas_binRenderer_open_fx( move16(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + hBinRenderer->numPoses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + } + else + { + hBinRenderer->numPoses = 1; + move16(); + } +#endif /* Declare some common variables needed for renderer */ /* Which format used for binaural rendering (needed for late reverb) ? MC or SBA */ @@ -1193,11 +1330,17 @@ ivas_error ivas_binRenderer_open_fx( IVAS_OUTPUT_SETUP out_setup; /* Allocate memories and buffers needed for convolutional module in CICP19 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, 1, IVAS_AUDIO_CONFIG_7_1_4, st_ivas->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, 1, IVAS_AUDIO_CONFIG_7_1_4, st_ivas->hHrtfFastConv ) ), IVAS_ERR_OK ) ) { return error; } - +#endif ivas_output_init( &out_setup, IVAS_AUDIO_CONFIG_7_1_4 ); IF( st_ivas->hoa_dec_mtx == NULL ) @@ -1215,10 +1358,17 @@ ivas_error ivas_binRenderer_open_fx( ELSE { /* Allocate memories and buffers needed for convolutional module */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, st_ivas->hIntSetup.is_loudspeaker_setup, st_ivas->hIntSetup.output_config, st_ivas->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, st_ivas->renderer_type, st_ivas->hIntSetup.is_loudspeaker_setup, st_ivas->hIntSetup.output_config, st_ivas->hHrtfFastConv ) ), IVAS_ERR_OK ) ) { return error; } +#endif IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) ) { @@ -1320,10 +1470,18 @@ ivas_error ivas_binRenderer_open_fx( * Close convolution module handle of fastconv binaural renderer *------------------------------------------------------------------------*/ static void ivas_binRenderer_convModuleClose_fx( +#ifdef SPLIT_REND_WITH_HEAD_ROT + BINAURAL_RENDERER_HANDLE *hBinRenderer, /* i/o: fastconv binaural renderer handle */ + const Word16 num_poses /* i : number of poses */ +#else BINAURAL_RENDERER_HANDLE *hBinRenderer /* i/o: fastconv binaural renderer handle */ +#endif ) { Word16 bandIdx, chIdx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 posIdx; +#endif BINRENDERER_CONV_MODULE_HANDLE_FX hBinRenConvModule; @@ -1361,6 +1519,42 @@ static void ivas_binRenderer_convModuleClose_fx( free( hBinRenConvModule->filterTapsRightImag_fx ); hBinRenConvModule->filterTapsRightImag_fx = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( posIdx = 0; posIdx < num_poses; posIdx++ ) + { + FOR( bandIdx = 0; bandIdx < ( *hBinRenderer )->conv_band; bandIdx++ ) + { + FOR( chIdx = 0; chIdx < ( *hBinRenderer )->nInChannels; chIdx++ ) + { + free( hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx][chIdx] ); + hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx][chIdx] = NULL; + + free( hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx][chIdx] ); + hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx][chIdx] = NULL; + + free( hBinRenConvModule->Q_filterStatesLeft[posIdx][bandIdx][chIdx] ); + hBinRenConvModule->Q_filterStatesLeft[posIdx][bandIdx][chIdx] = NULL; + } + + free( hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx] ); + hBinRenConvModule->filterStatesLeftReal_fx[posIdx][bandIdx] = NULL; + + free( hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx] ); + hBinRenConvModule->filterStatesLeftImag_fx[posIdx][bandIdx] = NULL; + + free( hBinRenConvModule->Q_filterStatesLeft[posIdx][bandIdx] ); + hBinRenConvModule->Q_filterStatesLeft[posIdx][bandIdx] = NULL; + } + free( hBinRenConvModule->filterStatesLeftReal_fx[posIdx] ); + hBinRenConvModule->filterStatesLeftReal_fx[posIdx] = NULL; + + free( hBinRenConvModule->filterStatesLeftImag_fx[posIdx] ); + hBinRenConvModule->filterStatesLeftImag_fx[posIdx] = NULL; + + free( hBinRenConvModule->Q_filterStatesLeft[posIdx] ); + hBinRenConvModule->Q_filterStatesLeft[posIdx] = NULL; + } +#else FOR( bandIdx = 0; bandIdx < ( *hBinRenderer )->conv_band; bandIdx++ ) { FOR( chIdx = 0; chIdx < ( *hBinRenderer )->nInChannels; chIdx++ ) @@ -1384,7 +1578,7 @@ static void ivas_binRenderer_convModuleClose_fx( free( hBinRenConvModule->Q_filterStatesLeft[bandIdx] ); hBinRenConvModule->Q_filterStatesLeft[bandIdx] = NULL; } - +#endif free( hBinRenConvModule->filterStatesLeftReal_fx ); hBinRenConvModule->filterStatesLeftReal_fx = NULL; @@ -1417,7 +1611,11 @@ void ivas_binRenderer_close_fx( IF( ( *hBinRenderer )->hBinRenConvModule != NULL ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_binRenderer_convModuleClose_fx( hBinRenderer, ( *hBinRenderer )->numPoses ); +#else ivas_binRenderer_convModuleClose_fx( hBinRenderer ); +#endif } IF( ( *hBinRenderer )->hReverb != NULL ) @@ -1526,6 +1724,7 @@ void ivas_binaural_add_LFE_fx( ) { Word16 render_lfe, idx_lfe, gain_fx; + Word32 lfe_tc[L_FRAME48k]; IF( st_ivas->hBinRenderer != NULL ) { @@ -1562,15 +1761,15 @@ void ivas_binaural_add_LFE_fx( } FOR( idx_lfe = 0; idx_lfe < st_ivas->hIntSetup.num_lfe; idx_lfe++ ) { - v_multc_fixed_16( input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]], gain_fx, input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]], output_frame ); // q_input_fx - 1 + v_multc_fixed_16( input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]], gain_fx, lfe_tc, output_frame ); // q_input_fx - 1 /* copy LFE to left and right channels */ FOR( int idx = 0; idx < output_frame; idx++ ) { - input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]][idx] = L_shl_sat( input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]][idx], 1 ); // saturating to keep same q + lfe_tc[idx] = L_shl_sat( lfe_tc[idx], 1 ); // saturating to keep same q move32(); - output_fx[0][idx] = L_add_sat( output_fx[0][idx], input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]][idx] ); + output_fx[0][idx] = L_add_sat( output_fx[0][idx], lfe_tc[idx] ); move32(); - output_fx[1][idx] = L_add_sat( output_fx[1][idx], input_fx[st_ivas->hIntSetup.index_lfe[idx_lfe]][idx] ); + output_fx[1][idx] = L_add_sat( output_fx[1][idx], lfe_tc[idx] ); move32(); } } @@ -1580,30 +1779,80 @@ void ivas_binaural_add_LFE_fx( } /*------------------------------------------------------------------------- - * ivas_binRenderer() + * ivas_binRenderer_fx() * * Fastconv binaural renderer main function *-------------------------------------------------------------------------*/ void ivas_binRenderer_fx( - BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */ - COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle*/ - const Word16 numTimeSlots, /* i : number of time slots to render */ + BINAURAL_RENDERER_HANDLE hBinRenderer, /* i/o: binaural renderer handle */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, +#endif + COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined head and external orientation handle*/ + const Word16 numTimeSlots, /* i : number of time slots to render */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 Cldfb_RealBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */ + Word32 Cldfb_ImagBuffer_Binaural_fx[][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Rotated Binaural signals */ +#else Word32 Cldfb_RealBuffer_Binaural_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals Q_in*/ Word32 Cldfb_ImagBuffer_Binaural_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals Q_in*/ - Word32 RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals Q_in*/ - Word32 ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals Q_in*/ - Word16 *Q_in /* i : LS signals exp */ +#endif + Word32 RealBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals Q_in*/ + Word32 ImagBuffer_fx[][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX], /* i : LS signals Q_in*/ + Word16 *Q_in /* i : LS signals exp */ ) { Word16 chIdx, i, j, k; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx, num_poses; + Word32 RealBuffer_local[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 ImagBuffer_local[MAX_OUTPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; +#endif + // to be checked: feasibility with 32 bit buffers Word64 Cldfb_RealBuffer_Binaural_64fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word64 Cldfb_ImagBuffer_Binaural_64fx[BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + push_wmops( "fastconv_binaural_rendering" ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + num_poses = hBinRenderer->numPoses; +#endif + /* Compute Convolution */ /* memory reset for the binaural output */ + +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + FOR( k = 0; k < numTimeSlots; k++ ) + { + set32_fx( Cldfb_RealBuffer_Binaural_fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set32_fx( Cldfb_ImagBuffer_Binaural_fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + } + } + } + FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + FOR( k = 0; k < numTimeSlots; k++ ) + { + set64_fx( Cldfb_RealBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set64_fx( Cldfb_ImagBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + } + } + + FOR( chIdx = 0; chIdx < hBinRenderer->hInputSetup->nchan_out_woLFE; chIdx++ ) + { + FOR( k = 0; k < numTimeSlots; k++ ) + { + mvr2r( RealBuffer_fx[chIdx][k], RealBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX ); + mvr2r( ImagBuffer_fx[chIdx][k], ImagBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX ); + } + } +#else FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) { FOR( k = 0; k < numTimeSlots; k++ ) @@ -1614,6 +1863,7 @@ void ivas_binRenderer_fx( set64_fx( Cldfb_ImagBuffer_Binaural_64fx[chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); } } +#endif /* Head rotation in HOA3 or CICPx */ test(); @@ -1651,7 +1901,12 @@ void ivas_binRenderer_fx( ivas_sba2mc_cldfb_fixed( *( hBinRenderer->hInputSetup ), RealBuffer_fx, ImagBuffer_fx, hBinRenderer->nInChannels, hBinRenderer->conv_band, numTimeSlots, hBinRenderer->hoa_dec_mtx ); } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_binRenderer_filterModule_fx( Cldfb_RealBuffer_Binaural_64fx, Cldfb_ImagBuffer_Binaural_64fx, RealBuffer_fx, ImagBuffer_fx, numTimeSlots, hBinRenderer, 0, *Q_in ); +#else ivas_binRenderer_filterModule_fx( Cldfb_RealBuffer_Binaural_64fx, Cldfb_ImagBuffer_Binaural_64fx, RealBuffer_fx, ImagBuffer_fx, numTimeSlots, hBinRenderer, *Q_in ); +#endif FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) { @@ -1659,13 +1914,118 @@ void ivas_binRenderer_fx( { FOR( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + Cldfb_RealBuffer_Binaural_fx[0][i][j][k] = W_extract_l( W_shr( Cldfb_RealBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 + move32(); + Cldfb_ImagBuffer_Binaural_fx[0][i][j][k] = W_extract_l( W_shr( Cldfb_ImagBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 + move32(); +#else Cldfb_RealBuffer_Binaural_fx[i][j][k] = W_extract_l( W_shr( Cldfb_RealBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 move32(); Cldfb_ImagBuffer_Binaural_fx[i][j][k] = W_extract_l( W_shr( Cldfb_ImagBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 move32(); +#endif + } + } + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( pMultiBinPoseData != NULL ) + { + IF( GT_16( pMultiBinPoseData->num_poses, 1 ) ) + { + IVAS_QUATERNION Quaternions_rel, Quaternions_abs, *Quaternions_ref; + Word32 Rmat_local[3][3]; + Word16 q_fact_orig; + + IF( hCombinedOrientationData && hBinRenderer->rotInCldfb ) + { + Quaternions_ref = &hCombinedOrientationData->Quaternions[0]; + Quaternions_rel.w_fx = L_negate( 12582912 ); // Q22 + Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 + q_fact_orig = Quaternions_ref->q_fact; + + Quaternions_ref->w_fx = L_shl( Quaternions_ref->w_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 + Quaternions_ref->x_fx = L_shl( Quaternions_ref->x_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 + Quaternions_ref->y_fx = L_shl( Quaternions_ref->y_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 + Quaternions_ref->z_fx = L_shl( Quaternions_ref->z_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 + + IF( EQ_16( hCombinedOrientationData->shd_rot_max_order, 0 ) ) + { + /*HOA signal already rotated by DirAC*/ + Quaternions_abs.x_fx = 0; + Quaternions_abs.y_fx = 0; + Quaternions_abs.z_fx = 0; + } + ELSE + { + /*euler*/ + Quat2EulerDegree_fx( *Quaternions_ref, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + } + + FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + FOR( chIdx = 0; chIdx < hBinRenderer->hInputSetup->nchan_out_woLFE; chIdx++ ) + { + FOR( k = 0; k < numTimeSlots; k++ ) + { + Copy32( RealBuffer_local[chIdx][k], RealBuffer_fx[chIdx][k], CLDFB_NO_CHANNELS_MAX ); + Copy32( ImagBuffer_local[chIdx][k], ImagBuffer_fx[chIdx][k], CLDFB_NO_CHANNELS_MAX ); + } + } + Quaternions_rel.x_fx = L_sub( pMultiBinPoseData->relative_head_poses_fx[pos_idx][0], pMultiBinPoseData->relative_head_poses_fx[pos_idx - 1][0] ); + Quaternions_rel.y_fx = L_sub( pMultiBinPoseData->relative_head_poses_fx[pos_idx][1], pMultiBinPoseData->relative_head_poses_fx[pos_idx - 1][1] ); + Quaternions_rel.z_fx = L_sub( pMultiBinPoseData->relative_head_poses_fx[pos_idx][2], pMultiBinPoseData->relative_head_poses_fx[pos_idx - 1][2] ); + Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, Quaternions_rel.x_fx ); + Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, Quaternions_rel.y_fx ); + Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, Quaternions_rel.z_fx ); + + Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), deg2rad_fx( Quaternions_abs.y_fx ), deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs ); + Quaternions_abs.w_fx = L_shl( Quaternions_abs.w_fx, Q7 ); // Q29 + Quaternions_abs.x_fx = L_shl( Quaternions_abs.x_fx, Q7 ); // Q29 + Quaternions_abs.y_fx = L_shl( Quaternions_abs.y_fx, Q7 ); // Q29 + Quaternions_abs.z_fx = L_shl( Quaternions_abs.z_fx, Q7 ); // Q29 + + QuatToRotMat_fx( Quaternions_abs, Rmat_local ); + + if ( hBinRenderer->hInputSetup->is_loudspeaker_setup ) + { + rotateFrame_sd_cldfb( Rmat_local, RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); + } + else + { + rotateFrame_shd_cldfb( RealBuffer_fx, ImagBuffer_fx, Rmat_local, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 ); + } + + FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) + { + FOR( k = 0; k < numTimeSlots; k++ ) + { + set64_fx( Cldfb_RealBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set64_fx( Cldfb_ImagBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + } + } + ivas_binRenderer_filterModule_fx( Cldfb_RealBuffer_Binaural_64fx, Cldfb_ImagBuffer_Binaural_64fx, RealBuffer_fx, ImagBuffer_fx, numTimeSlots, hBinRenderer, pos_idx, *Q_in ); + + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + { + FOR( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + { + Cldfb_RealBuffer_Binaural_fx[pos_idx][i][j][k] = W_extract_l( W_shr( Cldfb_RealBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 + move32(); + Cldfb_ImagBuffer_Binaural_fx[pos_idx][i][j][k] = W_extract_l( W_shr( Cldfb_ImagBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 + move32(); + } + } + } + } } } } +#endif + /* Obtain the binaural dmx and compute the reverb */ IF( hBinRenderer->hReverb != NULL ) { @@ -1706,12 +2066,99 @@ void ivas_binRenderer_fx( { FOR( k = 0; k < numTimeSlots; k++ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + /* Combine first and second parts to generate binaural output signal with room effect */ + v_add_32( Cldfb_RealBuffer_Binaural_fx[pos_idx][chIdx][k], reverbRe_fx[chIdx][k], Cldfb_RealBuffer_Binaural_fx[pos_idx][chIdx][k], hBinRenderer->conv_band ); // Q_in + v_add_32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][chIdx][k], reverbIm_fx[chIdx][k], Cldfb_ImagBuffer_Binaural_fx[pos_idx][chIdx][k], hBinRenderer->conv_band ); // Q_in + } +#else /* Combine first and second parts to generate binaural output signal with room effect */ v_add_32( Cldfb_RealBuffer_Binaural_fx[chIdx][k], reverbRe_fx[chIdx][k], Cldfb_RealBuffer_Binaural_fx[chIdx][k], hBinRenderer->conv_band ); // Q_in v_add_32( Cldfb_ImagBuffer_Binaural_fx[chIdx][k], reverbIm_fx[chIdx][k], Cldfb_ImagBuffer_Binaural_fx[chIdx][k], hBinRenderer->conv_band ); // Q_in +#endif } } } pop_wmops(); return; } + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*------------------------------------------------------------------------- + * ivas_rend_CldfbMultiBinRendProcess() + * + * + *-------------------------------------------------------------------------*/ + +void ivas_rend_CldfbMultiBinRendProcess( + const BINAURAL_RENDERER_HANDLE hCldfbRend, + const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Real[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ + Word32 Cldfb_Out_Imag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 low_res_pre_rend_rot, + const Word16 num_subframes, + Word16 *Q_in /* i : LS signals exp */ +) +{ + int16_t slot_idx, ch_idx, idx, pose_idx, i, j; + int16_t sf_idx; + Word32 Cldfb_RealBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + + FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) + { + FOR( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + idx = sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES + slot_idx; + FOR( ch_idx = 0; ch_idx < hCldfbRend->nInChannels; ch_idx++ ) + { + Copy32( &Cldfb_In_Real[ch_idx][idx][0], &Cldfb_RealBuffer_sfIn[ch_idx][slot_idx][0], hCldfbRend->max_band ); + Copy32( &Cldfb_In_Imag[ch_idx][idx][0], &Cldfb_ImagBuffer_sfIn[ch_idx][slot_idx][0], hCldfbRend->max_band ); + } + } + + if ( ( *pCombinedOrientationData ) != NULL ) + { + if ( ( low_res_pre_rend_rot ) && ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + { + ( *pCombinedOrientationData )->Quaternions[sf_idx] = ( *pCombinedOrientationData )->Quaternions[0]; + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < 3; j++ ) + { + ( *pCombinedOrientationData )->Rmat_fx[sf_idx][i][j] = ( *pCombinedOrientationData )->Rmat_fx[0][i][j]; + } + } + } + ( *pCombinedOrientationData )->shd_rot_max_order = -1; + } + + ivas_binRenderer_fx( hCldfbRend, pMultiBinPoseData, *pCombinedOrientationData, MAX_PARAM_SPATIAL_SUBFRAMES, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer_sfIn, Cldfb_ImagBuffer_sfIn, Q_in ); + + FOR( pose_idx = 0; pose_idx < hCldfbRend->numPoses; pose_idx++ ) + { + FOR( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + { + idx = sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES + slot_idx; + FOR( ch_idx = 0; ch_idx < BINAURAL_CHANNELS; ch_idx++ ) + { + Copy32( &Cldfb_RealBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band ); + Copy32( &Cldfb_ImagBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band ); + Scale_sig32( &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q6, *Q_in ) ); // Q6 + Scale_sig32( &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q6, *Q_in ) ); // Q6 + } + } + } + *Q_in = Q6; + } + + return; +} +#endif \ No newline at end of file diff --git a/lib_isar/isar_stat.h b/lib_isar/isar_stat.h index e94d23e18..4c3dd12e1 100644 --- a/lib_isar/isar_stat.h +++ b/lib_isar/isar_stat.h @@ -229,7 +229,7 @@ typedef struct isar_binaural_head_rot_split_post_rendering_struct typedef struct { int16_t num_poses; - float relative_head_poses[MAX_HEAD_ROT_POSES][3]; + // float relative_head_poses[MAX_HEAD_ROT_POSES][3]; Word32 relative_head_poses_fx[MAX_HEAD_ROT_POSES][3]; /* Q22 */ int16_t dof; int16_t hq_mode; diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 15381d5bd..14139c534 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1334,6 +1334,34 @@ typedef struct ivas_binaural_crend_wrapper_struct } CREND_WRAPPER, *CREND_WRAPPER_HANDLE; +#ifdef SPLIT_REND_WITH_HEAD_ROT +/* Fastconv binaural data structure */ +typedef struct ivas_binaural_rendering_struct +{ + /* Common variables for all modules */ + IVAS_OUTPUT_SETUP_HANDLE hInputSetup; /* pointer to input spatial format for binaural renderer*/ + EFAP_HANDLE hEFAPdata; /* EFAP structure*/ + Word32 *hoa_dec_mtx; /* pointer to HOA decoder mtx */ /*Q29*/ + int8_t rotInCldfb; /* Flag to enable rotation within bin Renderer in CLDFB*/ + int16_t max_band; /* band upto which rendering is performed */ + int16_t conv_band; /* band upto which convolution in cldfb domain is performed */ + int16_t timeSlots; /* number of time slots of binaural renderer */ + int16_t nInChannels; /* number input channels */ + int8_t render_lfe; /* Flag to render LFE in binaural rendering*/ + IVAS_FORMAT ivas_format; /* format; corresponds to st_ivas->ivas_format, unless the signal gets transormed to a different domain for rendering */ + + /* Convolution module structure */ + BINRENDERER_CONV_MODULE_HANDLE_FX hBinRenConvModule; + + /* Variables related to reverberator module */ + Word32 earlyPartEneCorrection_fx[CLDFB_NO_CHANNELS_MAX]; + REVERB_STRUCT_HANDLE hReverb; + + Word16 numPoses; + +} BINAURAL_RENDERER, *BINAURAL_RENDERER_HANDLE; +#endif + /*------------------------------------------------------------------------------------------* * HRTF structures - hrtfs from binary files *------------------------------------------------------------------------------------------*/ diff --git a/lib_util/split_rend_bfi_file_reader.c b/lib_util/split_rend_bfi_file_reader.c new file mode 100644 index 000000000..96b78972f --- /dev/null +++ b/lib_util/split_rend_bfi_file_reader.c @@ -0,0 +1,162 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "split_rend_bfi_file_reader.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "prot.h" + +struct SplitRendBFIFileReader +{ + FILE *bfiFile; + int32_t frameCounter; + char *file_path; + bool fileRewind; + bool txtfile; +}; + + +/*-----------------------------------------------------------------------* + * SplitRendBFIFileReader_open() + * + * Allocate and initialize Split Renderer Frameloss file reader + *-----------------------------------------------------------------------*/ + +ivas_error SplitRendBFIFileReader_open( + char *bfiFilePath, /* i : frame loss file name */ + SplitRendBFIFileReader **SplitRendBFIReader /* o : SplitRendBFIFileReader handle */ +) +{ + SplitRendBFIFileReader *self; + FILE *bfiFile; + bool txtfile; + + /* Open bfi file */ + if ( strlen( bfiFilePath ) < 1 ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + bfiFile = fopen( bfiFilePath, "r" ); + + if ( !bfiFile ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + txtfile = ( strcmp( bfiFilePath + strlen( bfiFilePath ) - 4, ".txt" ) ? false : true ); + + self = calloc( sizeof( SplitRendBFIFileReader ), 1 ); + self->bfiFile = bfiFile; + self->frameCounter = 0; + self->file_path = calloc( sizeof( char ), strlen( bfiFilePath ) + 1 ); + strcpy( self->file_path, bfiFilePath ); + self->fileRewind = false; + self->txtfile = txtfile; + + *SplitRendBFIReader = self; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * SplitRendBFIFileReading() + * + * Read values from the bfi file + *-----------------------------------------------------------------------*/ + +ivas_error SplitRendBFIFileReading( + SplitRendBFIFileReader *SplitRendBFIReader, /* i/o: SplitRendBFIFileReader handle */ + int16_t *bfi ) +{ + if ( SplitRendBFIReader->txtfile ? 1 != fscanf( SplitRendBFIReader->bfiFile, "%hd", bfi ) : 1 != fread( bfi, sizeof( *bfi ), 1, SplitRendBFIReader->bfiFile ) ) + { + if ( feof( SplitRendBFIReader->bfiFile ) ) + { + rewind( SplitRendBFIReader->bfiFile ); + SplitRendBFIReader->fileRewind = true; + return SplitRendBFIFileReading( SplitRendBFIReader, bfi ); + } + return IVAS_ERR_FAILED_FILE_PARSE; + } + + ( SplitRendBFIReader->frameCounter )++; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * SplitRendBFIationFileReader_close() + * + * Deallocates memory for the Head-Tracking reader + *-----------------------------------------------------------------------*/ + +void SplitRendBFIFileReader_close( + SplitRendBFIFileReader **SplitRendBFIReader /* i/o: SplitRendBFIFileReader handle */ +) +{ + if ( SplitRendBFIReader == NULL || *SplitRendBFIReader == NULL ) + { + return; + } + + fclose( ( *SplitRendBFIReader )->bfiFile ); + free( ( *SplitRendBFIReader )->file_path ); + free( *SplitRendBFIReader ); + *SplitRendBFIReader = NULL; + + return; +} + + +/*-----------------------------------------------------------------------* + * SplitRendBFIFileReader_getFilePath() + * + * + *-----------------------------------------------------------------------*/ + +const char *SplitRendBFIFileReader_getFilePath( + SplitRendBFIFileReader *SplitRendBFIReader /* i/o: SplitRendBFIFileReader handle */ +) +{ + if ( SplitRendBFIReader == NULL ) + { + return NULL; + } + + return SplitRendBFIReader->file_path; +} +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/lib_util/split_rend_bfi_file_reader.h b/lib_util/split_rend_bfi_file_reader.h new file mode 100644 index 000000000..341ef3ed6 --- /dev/null +++ b/lib_util/split_rend_bfi_file_reader.h @@ -0,0 +1,60 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef IVAS_SR_BFI_FILE_READER_H +#define IVAS_SR_BFI_FILE_READER_H + +#include "common_api_types.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT + +typedef struct SplitRendBFIFileReader SplitRendBFIFileReader; + +ivas_error SplitRendBFIFileReader_open( + char *trajFilePath, /* i : head rotation trajectory file name */ + SplitRendBFIFileReader **SplitRendBFIReader /* o : SplitRendBFIFileReader handle */ +); + +ivas_error SplitRendBFIFileReading( + SplitRendBFIFileReader *SplitRendBFIReader, /* i/o: SplitRendBFIFileReader handle */ + int16_t *bfi ); + +void SplitRendBFIFileReader_close( + SplitRendBFIFileReader **SplitRendBFIReader /* i/o: SplitRendBFIFileReader handle */ +); + +const char *SplitRendBFIFileReader_getFilePath( + SplitRendBFIFileReader *SplitRendBFIReader /* i/o: SplitRendBFIFileReader handle */ +); + + +#endif /* SPLIT_REND_WITH_HEAD_ROT */ +#endif /* IVAS_SR_BFI_FILE_READER_H */ diff --git a/lib_util/split_render_file_read_write.c b/lib_util/split_render_file_read_write.c new file mode 100644 index 000000000..8a4dea8fd --- /dev/null +++ b/lib_util/split_render_file_read_write.c @@ -0,0 +1,431 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "split_render_file_read_write.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT +#include +#include "prot.h" + + +/*------------------------------------------------------------------------------------------* + * PreProc Macros + *------------------------------------------------------------------------------------------*/ + +#define SPLIT_RENDERER_FRAME_HEADER_LEN ( 12 ) + +/*------------------------------------------------------------------------------------------* + * Type definitions + *------------------------------------------------------------------------------------------*/ + +struct SplitFileReadWrite +{ + FILE *file; + uint32_t delay_ns; +}; + + +/*-----------------------------------------------------------------------------------------* + * Function split_rend_reader_open() + * + * open in read mode + *-----------------------------------------------------------------------------------------*/ + +ivas_error split_rend_reader_open( + SplitFileReadWrite **hhSplitRendFileReadWrite, + char *filename, + ISAR_SPLIT_REND_CODEC *codec, + ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, + int16_t *codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + int16_t *isar_frame_size_ms, + int32_t *sampling_rate, + int16_t *lc3plus_highres +#endif +) +{ + SplitFileReadWrite *hSplitRendFileReadWrite; + size_t header_len, h; + char header[SPLIT_RENDERER_FRAME_HEADER_LEN] = "MAIN_SPLITH"; + char header_read[SPLIT_RENDERER_FRAME_HEADER_LEN]; + + if ( ( hSplitRendFileReadWrite = (SplitFileReadWrite *) malloc( sizeof( SplitFileReadWrite ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for split rendering writer\n" ) ); + } + + hSplitRendFileReadWrite->file = fopen( filename, "rb" ); + if ( hSplitRendFileReadWrite->file == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "\nCould not open split rend metadata file %s\n", filename ) ); + } + + header_len = strlen( header ); + + /*read frame header*/ + for ( h = 0; h < header_len; h++ ) + { + if ( fread( &header_read[h], sizeof( char ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + } + + if ( strncmp( header_read, header, header_len ) ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_FILE_READ, "\nError split rend bitstream main header mismatch\n" ) ); + } + + fread( &hSplitRendFileReadWrite->delay_ns, sizeof( uint32_t ), 1, hSplitRendFileReadWrite->file ); + + /* read codec signalling */ + if ( fread( codec, sizeof( *codec ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + + /* read pose correction signalling */ + if ( fread( poseCorrection, sizeof( *poseCorrection ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + /* read transport codec frame size signalling */ + if ( fread( codec_frame_size_ms, sizeof( *codec_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* read isar bitstream frame size signalling */ + if ( fread( isar_frame_size_ms, sizeof( *isar_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + /* read sampling rate signalling */ + if ( fread( sampling_rate, sizeof( *sampling_rate ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + /* read LC3plus highres signalling */ + if ( fread( lc3plus_highres, sizeof( *lc3plus_highres ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } +#endif + + *hhSplitRendFileReadWrite = hSplitRendFileReadWrite; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function split_rend_writer_open() + * + * open in write mode + *-----------------------------------------------------------------------------------------*/ + +ivas_error split_rend_writer_open( + SplitFileReadWrite **hhSplitRendFileReadWrite, + char *filename, + const int16_t delayNumSamples, + const int32_t delayTimeScale, + ISAR_SPLIT_REND_CODEC codec, + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection, + int16_t codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + const int16_t isar_frame_size_ms, + const int32_t sampling_rate, + const int16_t lc3plus_highres +#endif +) +{ + SplitFileReadWrite *hSplitRendFileReadWrite; + size_t header_len, h; + char header[SPLIT_RENDERER_FRAME_HEADER_LEN] = "MAIN_SPLITH"; + + if ( filename == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + if ( ( hSplitRendFileReadWrite = (SplitFileReadWrite *) malloc( sizeof( SplitFileReadWrite ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for split rendering writer\n" ) ); + } + + hSplitRendFileReadWrite->file = fopen( filename, "wb" ); + if ( hSplitRendFileReadWrite->file == NULL ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + header_len = strlen( header ); + + /* write frame header */ + for ( h = 0; h < header_len; h++ ) + { + if ( fwrite( &header[h], sizeof( char ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_END_OF_FILE; + } + } + hSplitRendFileReadWrite->delay_ns = (int32_t) ( (float) delayNumSamples * 1000000000.0f / (float) delayTimeScale ); + fwrite( &hSplitRendFileReadWrite->delay_ns, sizeof( int32_t ), 1, hSplitRendFileReadWrite->file ); + + /* Write codec signalling */ + if ( fwrite( &codec, sizeof( codec ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + + /* Write pose correction signalling */ + if ( fwrite( &poseCorrection, sizeof( poseCorrection ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + /* Write transport codec frame size signalling */ + if ( fwrite( &codec_frame_size_ms, sizeof( codec_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* Write isar bit stream frame size signalling */ + if ( fwrite( &isar_frame_size_ms, sizeof( isar_frame_size_ms ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + /* Write sampling rate signalling */ + if ( fwrite( &sampling_rate, sizeof( sampling_rate ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + /* Write LC3plus highres signalling */ + if ( fwrite( &lc3plus_highres, sizeof( lc3plus_highres ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } +#endif + + *hhSplitRendFileReadWrite = hSplitRendFileReadWrite; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function split_rend_reader_writer_close() + * + * + *-----------------------------------------------------------------------------------------*/ + +void split_rend_reader_writer_close( + SplitFileReadWrite **hhSplitRendFileReadWrite ) +{ + if ( ( *hhSplitRendFileReadWrite ) != NULL ) + { + if ( ( *hhSplitRendFileReadWrite )->file != NULL ) + { + fclose( ( *hhSplitRendFileReadWrite )->file ); + ( *hhSplitRendFileReadWrite )->file = NULL; + } + + free( *hhSplitRendFileReadWrite ); + *hhSplitRendFileReadWrite = NULL; + } + + return; +} + + +/*-----------------------------------------------------------------------------------------* + * Function split_rend_write_bitstream_to_file() + * + * + *-----------------------------------------------------------------------------------------*/ + +ivas_error split_rend_write_bitstream_to_file( + SplitFileReadWrite *hSplitRendFileReadWrite, + uint8_t *bits, + int32_t *bits_read, + int32_t *bits_written ) +{ + char header[SPLIT_RENDERER_FRAME_HEADER_LEN] = "SPLIT_FRAME"; + size_t header_len, i, num_bytes; + uint8_t version = 0; + + if ( hSplitRendFileReadWrite == NULL ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + + if ( hSplitRendFileReadWrite->file == NULL ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + + header_len = strlen( header ); + + /* write frame header */ + for ( i = 0; i < header_len; i++ ) + { + if ( fwrite( &header[i], sizeof( char ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + } + + /* Write versioning signalling */ + if ( fwrite( &version, 1, 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + + /* write num bytes */ + if ( fwrite( bits_written, sizeof( int32_t ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + + num_bytes = ( *bits_written + 7 ) >> 3; + if ( fwrite( bits, sizeof( uint8_t ), num_bytes, hSplitRendFileReadWrite->file ) != num_bytes ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + + *bits_read = 0; + *bits_written = 0; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function split_rend_read_bits_from_file() + * + * + *-----------------------------------------------------------------------------------------*/ + +ivas_error split_rend_read_bits_from_file( + SplitFileReadWrite *hSplitRendFileReadWrite, + uint8_t *bits, + int32_t *bits_read, + int32_t *bits_written ) +{ + char header[SPLIT_RENDERER_FRAME_HEADER_LEN] = "SPLIT_FRAME"; + char header_read[SPLIT_RENDERER_FRAME_HEADER_LEN]; + int32_t header_len, i, num_bytes, bit_len = 0; + uint8_t version; + + if ( hSplitRendFileReadWrite == NULL ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + + if ( hSplitRendFileReadWrite->file == NULL ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + + header_len = (int32_t) strlen( header ); + + /* read frame header */ + for ( i = 0; i < header_len; i++ ) + { + if ( fread( &header_read[i], sizeof( char ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_END_OF_FILE; + } + } + + if ( strncmp( header_read, header, header_len ) ) + { + fprintf( stderr, "Error bitstream frame header mismatch\n" ); + return IVAS_ERR_FAILED_FILE_READ; + } + + /* read versioning signalling */ + if ( fread( &version, 1, 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_WRITE; + } + if ( version != 0 ) + { + fprintf( stderr, "Error bitstream version mismatch\n" ); + return IVAS_ERR_FAILED_FILE_READ; + } + + /* write num bytes */ + if ( fread( &bit_len, sizeof( int32_t ), 1, hSplitRendFileReadWrite->file ) != 1 ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + num_bytes = ( bit_len + 7 ) >> 3; + + if ( fread( bits, sizeof( uint8_t ), num_bytes, hSplitRendFileReadWrite->file ) != (uint32_t) num_bytes ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + for ( i = 0; i < ISAR_SPLIT_REND_ADDITIONAL_BYTES_TO_READ; i++ ) + { + bits[num_bytes + i] = 0; + } + + *bits_read = 0; + *bits_written = bit_len; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function split_rend_read_pre_rend_delay_ns() + * + * + *-----------------------------------------------------------------------------------------*/ + +ivas_error split_rend_read_pre_rend_delay_ns( + SplitFileReadWrite *hSplitRendFileReadWrite, + uint32_t *delay_ns ) +{ + if ( hSplitRendFileReadWrite == NULL ) + { + return IVAS_ERR_FAILED_FILE_READ; + } + + *delay_ns = hSplitRendFileReadWrite->delay_ns; + + return IVAS_ERR_OK; +} +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/lib_util/split_render_file_read_write.h b/lib_util/split_render_file_read_write.h new file mode 100644 index 000000000..1d6529ef2 --- /dev/null +++ b/lib_util/split_render_file_read_write.h @@ -0,0 +1,99 @@ +/****************************************************************************************************** + + (C) 2022-2023 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. + +*******************************************************************************************************/ + +#ifndef SPLIT_RENDER_FILE_READ_WRITE_H +#define SPLIT_RENDER_FILE_READ_WRITE_H + +#include "common_api_types.h" +#ifdef SPLIT_REND_WITH_HEAD_ROT + +typedef struct SplitFileReadWrite SplitFileReadWrite; + +/* Allocates and initializes a a split renderer reader instance */ +ivas_error split_rend_reader_open( + SplitFileReadWrite **hhSplitRendFileReadWrite, + char *filename, + ISAR_SPLIT_REND_CODEC *codec, + ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, + int16_t *codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + int16_t *isar_frame_size_ms, + int32_t *sampling_rate, + int16_t *lc3plus_highres +#endif +); + + +/* Allocates and initializes a a split renderer writer instance */ +ivas_error split_rend_writer_open( + SplitFileReadWrite **hhSplitRendFileReadWrite, + char *filename, + const int16_t delayNumSamples, + const int32_t delayTimeScale, + ISAR_SPLIT_REND_CODEC codec, + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection, + int16_t codec_frame_size_ms +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + const int16_t isar_frame_size_ms, + const int32_t sampling_rate, + const int16_t lc3plus_highres +#endif +); + + +/* Closes the split renderer reader/writer and deallocates memory */ +void split_rend_reader_writer_close( + SplitFileReadWrite **hhSplitRendFileReadWrite ); + +/*write split rend coded bitstream to file */ +ivas_error split_rend_write_bitstream_to_file( + SplitFileReadWrite *hSplitRendFileReadWrite, + uint8_t *bits, + int32_t *bits_read, + int32_t *bits_written ); + +/* read split rend coded bits from file */ +ivas_error split_rend_read_bits_from_file( + SplitFileReadWrite *hSplitRendFileReadWrite, + uint8_t *bits, + int32_t *bits_read, + int32_t *bits_written ); + +/* read split pre rend delay */ +ivas_error split_rend_read_pre_rend_delay_ns( + SplitFileReadWrite *hSplitRendFileReadWrite, + uint32_t *delay_ns ); + +#endif /* SPLIT_REND_WITH_HEAD_ROT */ +#endif /* SPLIT_RENDER_FILE_READ_WRITE_H */ -- GitLab From 8f9f26cbe5fc748f3b85153f309129c4275a5156 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 29 Jan 2025 01:15:27 +1100 Subject: [PATCH 03/43] lib decoder split rendering BASOP updates --- apps/decoder.c | 76 ++-- lib_dec/lib_dec.h | 53 ++- lib_dec/lib_dec_fx.c | 687 ++++++++++++++++++++++++++++++++++- lib_isar/isar_stat.h | 2 +- lib_isar/lib_isar_pre_rend.c | 13 +- lib_isar/lib_isar_pre_rend.h | 1 - 6 files changed, 779 insertions(+), 53 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index 65c949ace..77126067e 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -181,7 +181,7 @@ int main( #endif #ifdef SPLIT_REND_WITH_HEAD_ROT - splitRendBits.bits_buf = splitRendBitsBuf; + splitRendBits.bits_buf = splitRendBitsBuf; #endif /*------------------------------------------------------------------------------------------* @@ -1463,14 +1463,14 @@ static void usage_dec( void ) *---------------------------------------------------------------------*/ static ivas_error initOnFirstGoodFrame( - IVAS_DEC_HANDLE hIvasDec, /* i/o: */ - const DecArguments arg, /* i : */ - const int16_t numInitialBadFrames, /* i : */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: */ + const DecArguments arg, /* i : */ + const int16_t numInitialBadFrames, /* i : */ #ifdef SPLIT_REND_WITH_HEAD_ROT int16_t *numOutSamples, /* i/o: */ int16_t *vec_pos_len, /* i/o: */ #else - const uint16_t numOutSamples, /* i : */ + const uint16_t numOutSamples, /* i : */ #endif int16_t *pFullDelayNumSamples, /* o : */ int16_t *pRemainingDelayNumSamples, /* o : */ @@ -1484,7 +1484,7 @@ static ivas_error initOnFirstGoodFrame( uint16_t *pNumObj, /* o : */ SplitFileReadWrite **splitRendWriter #else - uint16_t *pNumObj /* o : */ + uint16_t *pNumObj /* o : */ #endif ) { @@ -1614,12 +1614,12 @@ static ivas_error initOnFirstGoodFrame( if ( IVAS_DEC_is_split_rendering_coded_out( hIvasDec ) == 0 ) { #endif - /* Open audio writer and write all previously skipped bad frames now that frame size is known */ - if ( ( error = AudioFileWriter_open( ppAfWriter, arg.outputWavFilename, arg.output_Fs, *pNumOutChannels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); - return error; - } + /* Open audio writer and write all previously skipped bad frames now that frame size is known */ + if ( ( error = AudioFileWriter_open( ppAfWriter, arg.outputWavFilename, arg.output_Fs, *pNumOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nUnable to open output file %s\n", arg.outputWavFilename ); + return error; + } #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif @@ -1661,20 +1661,20 @@ static ivas_error initOnFirstGoodFrame( #else if ( *pRemainingDelayNumSamples < numOutSamples ) #endif - { + { #ifdef SPLIT_REND_WITH_HEAD_ROT if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, *numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) #else if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) #endif - { - fprintf( stderr, "\nOutput audio file writer error\n" ); - return error; + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + return error; + } + *pRemainingDelayNumSamples = 0; } - *pRemainingDelayNumSamples = 0; - } - else - { + else + { #ifdef SPLIT_REND_WITH_HEAD_ROT *pRemainingDelayNumSamples -= *numOutSamples; #else @@ -2034,7 +2034,7 @@ static ivas_error decodeG192( #ifdef SPLIT_REND_WITH_HEAD_ROT if ( IVAS_DEC_is_split_rendering_enabled( hIvasDec ) ) { - if ( ( error = IVAS_DEC_GetSplitBinauralBitstream( hIvasDec, (void *) ( pcmBuf + nOutChannels * nSamplesRendered ), splitRendBits, &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_GetSplitBinauralBitstream( hIvasDec, (Word16 *) ( pcmBuf + nOutChannels * nSamplesRendered ), splitRendBits, &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_GetSplitBinauralBitstream: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -2053,12 +2053,12 @@ static ivas_error decodeG192( if ( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, ( pcmBuf + nOutChannels * nSamplesRendered ), &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) #endif - { - fprintf( stderr, "\nError in IVAS_DEC_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); - goto cleanup; - } - nSamplesRendered += nSamplesRendered_loop; - nSamplesToRender -= nSamplesRendered_loop; + { + fprintf( stderr, "\nError in IVAS_DEC_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; + } + nSamplesRendered += nSamplesRendered_loop; + nSamplesToRender -= nSamplesRendered_loop; #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif @@ -2123,19 +2123,19 @@ static ivas_error decodeG192( if ( IVAS_DEC_is_split_rendering_coded_out( hIvasDec ) == 0 ) { #endif - if ( delayNumSamples < nOutSamples ) - { - if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) + if ( delayNumSamples < nOutSamples ) { - fprintf( stderr, "\nOutput audio file writer error\n" ); - goto cleanup; + if ( ( error = AudioFileWriter_write( afWriter, &pcmBuf[delayNumSamples * nOutChannels], nOutSamples * nOutChannels - ( delayNumSamples * nOutChannels ) ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + goto cleanup; + } + delayNumSamples = 0; + } + else + { + delayNumSamples -= nOutSamples; } - delayNumSamples = 0; - } - else - { - delayNumSamples -= nOutSamples; - } #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 28fbe71b9..0b20e64f9 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -144,6 +144,46 @@ ivas_error IVAS_DEC_GetSamples( bool *needNewFrame /* o : indication that the decoder needs a new frame */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +ivas_error IVAS_DEC_GetSplitBinauralBitstream( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + void *pcmBuf_out, /* o : output synthesis signal for BINAURAL_SPLIT_PCM */ + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ + Word16 *nOutSamples, /* o : number of samples per channel written to output buffer */ + bool *needNewFrame /* o : indication that the decoder needs a new frame */ +); + +/*! r: decoder error code */ +ivas_error IVAS_DEC_GetSplitRendBitstreamHeader( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */ + ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 *pIsar_frame_size_ms, /* o: pointer to isar frame size setting */ +#endif + Word16 *pCodec_frame_size_ms /* o: pointer to codec frame size setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + Word16 *pLc3plusHighRes /* o: pointer to LC3plus High-Res setting */ +#endif +); + +/*! r: decoder error code */ +ivas_error IVAS_DEC_GetCldfbSamples( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + Word32 *out_real, /* o : buffer for decoded PCM real output in CLDFB domain */ + Word32 *out_imag, /* o : buffer for decoded PCM imag output in CLDFB domain */ + IVAS_AUDIO_CONFIG *audio_config, /* o : audio configuration */ + Word16 *nOutSamples /* o : number of samples per channel written to output buffer */ +); + +int16_t IVAS_DEC_is_split_rendering_enabled( + IVAS_DEC_HANDLE hIvasDec /* i: IVAS decoder handle */ +); +int16_t IVAS_DEC_is_split_rendering_coded_out( + IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +); +#endif /*! r: error code */ ivas_error IVAS_DEC_GetObjectMetadata( @@ -165,7 +205,12 @@ ivas_error IVAS_DEC_FeedHeadTrackData( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ IVAS_QUATERNION orientation, /* i : head-tracking data, listener orientation */ IVAS_VECTOR3 Pos, /* i : listener position */ - const Word16 subframe_idx /* i : subframe index */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 subframe_idx, /* i : subframe index */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i : external control for rotation axis for split rendering */ +#else + const Word16 subframe_idx /* i : subframe index */ +#endif ); /*! r: error code */ @@ -242,6 +287,12 @@ ivas_error IVAS_DEC_EnableVoIP( const IVAS_DEC_INPUT_FORMAT inputFormat /* i : format of the input bitstream */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*! r: error code */ +ivas_error IVAS_DEC_EnableSplitRendering( + IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +); +#endif ivas_error IVAS_DEC_SetRenderFramesize( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 7e2e69ec4..8e1edc657 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -40,6 +40,8 @@ #include "prot.h" #include "ivas_prot_fx.h" #include "prot_fx.h" +#include "isar_prot.h" +#include "lib_isar_pre_rend.h" #include "jbm_jb4sb.h" #include "jbm_pcmdsp_apa.h" @@ -117,7 +119,11 @@ static ivas_error IVAS_DEC_RendererFeedTcSamples( IVAS_DEC_HANDLE hIvasDec, cons static ivas_error IVAS_DEC_GetRenderedSamples( IVAS_DEC_HANDLE hIvasDec, const UWord16 nSamplesForRendering, UWord16 *nSamplesRendered, UWord16 *nSamplesAvailableNext, Word16 *pcmBuf ); static ivas_error IVAS_DEC_GetBufferedNumberOfSamples( IVAS_DEC_HANDLE hIvasDec, Word16 *nSamplesBuffered ); static Word16 get_render_frame_size_ms( IVAS_RENDER_FRAMESIZE render_framesize ); - +#ifdef SPLIT_REND_WITH_HEAD_ROT +static ivas_error isar_set_split_rend_setup( ISAR_DEC_SPLIT_REND_WRAPPER *hSplitBinRend, const ISAR_SPLIT_REND_CONFIG_DATA *hSplitBinConfig, const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, ISAR_SPLIT_REND_BITS_DATA *splitRendBits ); +static ivas_error ivas_create_handle_isar( ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE *hSplitBinRend_out ); +static void ivas_destroy_handle_isar( ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE *hSplitBinRend_out ); +#endif /*---------------------------------------------------------------------* * IVAS_DEC_Open() @@ -275,6 +281,46 @@ ivas_error IVAS_DEC_Open( return IVAS_ERR_WRONG_PARAMS; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-------------------------------------------------------------------------* + * isar_set_split_rend_setup() + * + * Setup IVAS split rendering + *-------------------------------------------------------------------------*/ + +static ivas_error isar_set_split_rend_setup( + ISAR_DEC_SPLIT_REND_WRAPPER *hSplitBinRend, + const ISAR_SPLIT_REND_CONFIG_DATA *hSplitBinConfig, + const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, + ISAR_SPLIT_REND_BITS_DATA *splitRendBits /* o : output split rendering bits */ +) +{ + splitRendBits->bits_read = 0; + splitRendBits->bits_written = 0; + splitRendBits->buf_len = ISAR_MAX_SPLIT_REND_BITS_BUFFER_SIZE_IN_BYTES; + splitRendBits->codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + splitRendBits->pose_correction = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + splitRendBits->codec_frame_size_ms = 0; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + splitRendBits->isar_frame_size_ms = 0; + splitRendBits->lc3plus_highres = 0; +#endif + + if ( ( hSplitBinRend->hMultiBinCldfbData = (ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for split rendering structure" ); + } + + ISAR_PRE_REND_GetMultiBinPoseData( hSplitBinConfig, &hSplitBinRend->splitrend.multiBinPoseData, ( hCombinedOrientationData != NULL ) ? hCombinedOrientationData->sr_pose_pred_axis : DEFAULT_AXIS ); + + if ( hCombinedOrientationData != NULL ) + { + isar_set_split_rend_ht_setup_fx( &hSplitBinRend->splitrend, hCombinedOrientationData->Quaternions, hCombinedOrientationData->Rmat_fx ); + } + + return IVAS_ERR_OK; +} +#endif /*---------------------------------------------------------------------* * init_decoder_config() @@ -297,6 +343,10 @@ static void init_decoder_config( hDecoderConfig->Opt_non_diegetic_pan = 0; hDecoderConfig->non_diegetic_pan_gain_fx = 0; // Q15 hDecoderConfig->Opt_tsm = 0; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hDecoderConfig->Opt_Limiter = 1; + move16(); +#endif hDecoderConfig->Opt_delay_comp = 0; hDecoderConfig->Opt_ExternalOrientation = 0; hDecoderConfig->Opt_dpid_on = 0; @@ -343,6 +393,11 @@ void IVAS_DEC_Close( ( *phIvasDec )->hVoIP = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* destroy Split binaural renderer (ISAR) handle */ + ivas_destroy_handle_isar( &( *phIvasDec )->st_ivas->hSplitBinRend ); +#endif + IF( ( *phIvasDec )->st_ivas ) { ivas_destroy_dec_fx( ( *phIvasDec )->st_ivas ); @@ -528,12 +583,31 @@ ivas_error IVAS_DEC_Configure( move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + hDecoderConfig->Opt_Headrotation = TRUE; + move16(); + } +#endif + /* Set decoder parameters to initial values */ IF( NE_32( ( error = ivas_init_decoder_front( st_ivas ) ), IVAS_ERR_OK ) ) { return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* create ISAR handle */ + IF( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( ( error = ivas_create_handle_isar( &st_ivas->hSplitBinRend ) ) != IVAS_ERR_OK ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for ISAR handle" ); + } + } +#endif + if ( EQ_16( hIvasDec->mode, IVAS_DEC_MODE_EVS ) ) { hIvasDec->st_ivas->ivas_format = MONO_FORMAT; @@ -555,6 +629,43 @@ ivas_error IVAS_DEC_Configure( return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*---------------------------------------------------------------------* + * IVAS_DEC_EnableSplitRendering( ) + * + * Intitialize Split rendering + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_EnableSplitRendering( + IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +) +{ + DECODER_CONFIG_HANDLE hDecoderConfig; + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hDecoderConfig = hIvasDec->st_ivas->hDecoderConfig; + move32(); + + hDecoderConfig->Opt_Headrotation = 1; + move16(); + hDecoderConfig->render_framesize = IVAS_RENDER_FRAMESIZE_20MS; + move32(); + + hDecoderConfig->Opt_Limiter = 0; + move16(); + + return error; +} +#endif /*---------------------------------------------------------------------* * get_render_framesize_ms( ) @@ -599,6 +710,16 @@ ivas_error IVAS_DEC_SetRenderFramesize( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } + IF( hIvasDec->st_ivas->hExtOrientationData != NULL ) + { + hIvasDec->st_ivas->hExtOrientationData->num_subframes = (Word16) render_framesize; + } + IF( hIvasDec->st_ivas->hCombinedOrientationData != NULL ) + { + hIvasDec->st_ivas->hCombinedOrientationData->num_subframes = (Word16) render_framesize; + } + + hIvasDec->st_ivas->hDecoderConfig->render_framesize = render_framesize; move16(); @@ -1006,6 +1127,21 @@ ivas_error IVAS_DEC_GetSamples( { return error; } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + /*----------------------------------------------------------------* + * Binaural split rendering setup + *----------------------------------------------------------------*/ + + IF( EQ_32( hIvasDec->st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hIvasDec->st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( hIvasDec->st_ivas->hCombinedOrientationData != NULL ) + { + isar_set_split_rend_ht_setup_fx( &hIvasDec->st_ivas->hSplitBinRend->splitrend, hIvasDec->st_ivas->hCombinedOrientationData->Quaternions, hIvasDec->st_ivas->hCombinedOrientationData->Rmat_fx ); + } + } +#endif + hIvasDec->updateOrientation = false; move16(); } @@ -1168,6 +1304,276 @@ return IVAS_ERR_OK; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*---------------------------------------------------------------------* + * IVAS_DEC_GetSplitBinauralBitstream( ) + * + * + *---------------------------------------------------------------------*/ + +ivas_error +IVAS_DEC_GetSplitBinauralBitstream( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + Word16 *pcmBuf_out, /* o : output synthesis signal for BINAURAL_SPLIT_PCM */ + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ + Word16 *nOutSamples, /* o : number of samples per channel written to output buffer */ + bool *needNewFrame /* o : indication that the decoder needs a new frame */ +) +{ + Decoder_Struct *st_ivas; + AUDIO_CONFIG output_config; + Word32 output_Fs; + Word32 *pOutput[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + Word32 output[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; + Word16 pcmBuf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES * L_FRAME48k]; + Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + FOR( Word32 i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + FOR( Word32 j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + FOR( Word32 k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + { + Cldfb_RealBuffer_Binaural[i][j][k] = 0; + Cldfb_ImagBuffer_Binaural[i][j][k] = 0; + move32(); + move32(); + } + } + } + Word16 numSamplesPerChannelToDecode; + Word16 i, j; + ivas_error error; + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; + Word16 max_band; + Word16 pcm_out_flag; + Word16 td_input; + Word16 numPoses; + Word16 slots_rendered, slots_rendered_new; + Word16 ro_md_flag; + IVAS_QUATERNION Quaternion; + + error = IVAS_ERR_OK; + st_ivas = hIvasDec->st_ivas; + output_config = st_ivas->hDecoderConfig->output_config; + output_Fs = st_ivas->hDecoderConfig->output_Fs; + numSamplesPerChannelToDecode = (Word16) ( output_Fs / FRAMES_PER_SEC ); // TODO remove division + + *needNewFrame = false; + hSplitBinRend = st_ivas->hSplitBinRend; + + if ( ( error = isar_set_split_rend_setup( hSplitBinRend, &st_ivas->hRenderConfig->split_rend_config, st_ivas->hCombinedOrientationData, splitRendBits ) ) != IVAS_ERR_OK ) + { + return error; + } + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + set32_fx( hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[i][j], 0, CLDFB_NO_CHANNELS_MAX ); + set32_fx( hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[i][j], 0, CLDFB_NO_CHANNELS_MAX ); + } + } + + numPoses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); + + IF( NE_32( st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_20MS ) && + ( EQ_32( hIvasDec->st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) || + EQ_16( hIvasDec->st_ivas->hRenderConfig->split_rend_config.dof, 0 ) ) ) + { + numSamplesPerChannelToDecode = (Word16) ( output_Fs / FRAMES_PER_SEC ); // TODO remove division + numSamplesPerChannelToDecode = (Word16) ( numSamplesPerChannelToDecode / MAX_PARAM_SPATIAL_SUBFRAMES ); // TODO remove division + numSamplesPerChannelToDecode *= (Word16) st_ivas->hDecoderConfig->render_framesize; + move16(); + move16(); + } + + IF( EQ_16( IVAS_DEC_is_split_rendering_enabled( hIvasDec ), 0 ) ) + { + return IVAS_ERR_WRONG_PARAMS; + } + + IF( st_ivas->hTcBuffer == NULL || hIvasDec->hasBeenFedFrame ) + { + slots_rendered = 0; + } + ELSE + { + /* this is needed for OMASA-DISC, because the td-rend granularity is 240 samples at 48kHz, leading to wrong slot count. */ + IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + slots_rendered = st_ivas->hTcBuffer->n_samples_rendered / NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); // TODO remove division + } + else + { + slots_rendered = st_ivas->hTcBuffer->n_samples_rendered / st_ivas->hTcBuffer->n_samples_granularity; + } + } + + + /* Decode and render */ + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, numSamplesPerChannelToDecode, pcmBuf, nOutSamples, needNewFrame ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* change buffer layout */ + FOR( i = 0; i < numSamplesPerChannelToDecode; ++i ) + { + FOR( j = 0; j < BINAURAL_CHANNELS * numPoses; ++j ) + { + output[j][i] = (Word32) pcmBuf[add( i_mult( i, i_mult( BINAURAL_CHANNELS, numPoses ) ), j )]; + move32(); + } + } + + FOR( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) + { + pOutput[i] = output[i]; + move32(); + } + + IF( st_ivas->hTcBuffer == NULL ) + { + slots_rendered_new = 0; + move16(); + } + ELSE + { + /* this is needed for OMASA-DISC, because the td-rend granularity is 240 samples at 48kHz, leading to wrong slot count. */ + IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + slots_rendered_new = st_ivas->hTcBuffer->n_samples_rendered / NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS ); // TODO remove division + } + ELSE + { + slots_rendered_new = st_ivas->hTcBuffer->n_samples_rendered / st_ivas->hTcBuffer->n_samples_granularity; // TODO remove division + } + } + + FOR( i = 0; i < i_mult( BINAURAL_CHANNELS, numPoses ); ++i ) + { + FOR( j = slots_rendered; j < slots_rendered_new; ++j ) + { + Copy32( hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[i][j], Cldfb_RealBuffer_Binaural[i][j - slots_rendered], CLDFB_NO_CHANNELS_MAX ); + Copy32( hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[i][j], Cldfb_ImagBuffer_Binaural[i][j - slots_rendered], CLDFB_NO_CHANNELS_MAX ); + } + } + + max_band = (Word16) ( ( BINAURAL_MAXBANDS * output_Fs ) / 48000 ); // TODO remove division + move16(); + pcm_out_flag = ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; + td_input = st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM && st_ivas->renderer_type != RENDERER_STEREO_PARAMETRIC; + + IF( st_ivas->hBinRendererTd != NULL ) + { + ro_md_flag = 1; + move16(); + } + ELSE + { + ro_md_flag = 0; + move16(); + } + + IF( st_ivas->hHeadTrackData != NULL ) + { + Quaternion = st_ivas->hHeadTrackData->Quaternions[0]; + } + ELSE + { + Quaternion.w_fx = -12582912; + Quaternion.x_fx = 0; + Quaternion.y_fx = 0; + Quaternion.z_fx = 0; + } + Word16 q1 = 31, q2 = 31, Q_buff; + Word16 Q_out[CLDFB_NO_COL_MAX]; + Q_out[0] = 31; + Word16 num_poses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; + + for ( i = 0; i < 16; i++ ) + { + for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + q1 = s_min( q1, L_norm_arr( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) ); + q2 = s_min( q2, L_norm_arr( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) ); + } + } + Q_buff = s_min( q1, q2 ); + for ( i = 0; i < 16; i++ ) + { + for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + scale_sig32( Cldfb_RealBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + } + } + Q_buff = Q_buff + Q6; + + IF( NE_16( td_input, 0 ) ) + { + /*TD input*/ + /*if CLDFB handles have been allocated then assume valid multi binaural input in out[][] buffer and perform CLDFB analysis*/ + /* local float2fix, to be removed */ + num_poses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; + + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + Q_out[0] = s_min( Q_out[0], L_norm_arr( output[i], L_FRAME48k ) ); + } + + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + scale_sig32( output[i], Q_out[0], L_FRAME48k ); + } + } + if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hSplitBinRend->splitrend, + Quaternion, + st_ivas->hRenderConfig->split_rend_config.splitRendBitRate, + st_ivas->hRenderConfig->split_rend_config.codec, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + st_ivas->hRenderConfig->split_rend_config.isar_frame_size_ms, +#endif + st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms, + splitRendBits, + Cldfb_RealBuffer_Binaural, + Cldfb_ImagBuffer_Binaural, + max_band, pOutput, 1, !td_input, pcm_out_flag, ro_md_flag, Q_buff, &Q_out[0] ) ) != IVAS_ERR_OK ) + + { + return error; + } + + /* convert to int16 with limiting for BINAURAL_SPLIT_PCM */ + IF( pcm_out_flag ) + { + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + scale_sig32( pOutput[j], numSamplesPerChannelToDecode, sub( Q11, Q_out[j] ) ); // Q11 + } + IF( EQ_32( st_ivas->hDecoderConfig->render_framesize, IVAS_RENDER_FRAMESIZE_5MS ) ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec_fx( st_ivas->hLimiter, pOutput, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToDecode, st_ivas->BER_detect, Q11 ); +#endif + } + else + { + ivas_limiter_dec_fx( st_ivas->hLimiter, pOutput, st_ivas->hDecoderConfig->nchan_out, numSamplesPerChannelToDecode, st_ivas->BER_detect, Q11 ); + } + + ivas_syn_output_fx( pOutput, Q11, numSamplesPerChannelToDecode, st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf_out ); + } + + free( st_ivas->hSplitBinRend->hMultiBinCldfbData ); + + return error; +} +#endif + + /*---------------------------------------------------------------------* * IVAS_DEC_Setup( ) * @@ -1836,7 +2242,12 @@ ivas_error IVAS_DEC_FeedHeadTrackData( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ IVAS_QUATERNION orientation, /* i : head-tracking data, listener orientation */ IVAS_VECTOR3 Pos, /* i : listener position */ - const Word16 subframe_idx /* i : subframe index */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 subframe_idx, /* i : subframe index */ + const ISAR_SPLIT_REND_ROT_AXIS rot_axis /* i : external control for rotation axis for split rendering */ +#else + const Word16 subframe_idx /* i : subframe index */ +#endif ) { HEAD_TRACK_DATA_HANDLE hHeadTrackData; @@ -1857,6 +2268,7 @@ ivas_error IVAS_DEC_FeedHeadTrackData( /* Move head-tracking data to the decoder handle */ /* check for Euler angle signaling */ + // TODO change euler angle to Q22 format IF( EQ_32( orientation.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) { Euler2Quat_fx( deg2rad_fx( orientation.x_fx ), deg2rad_fx( orientation.y_fx ), deg2rad_fx( orientation.z_fx ), &orientation ); @@ -1898,6 +2310,11 @@ ivas_error IVAS_DEC_FeedHeadTrackData( move32(); move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + hHeadTrackData->sr_pose_pred_axis = rot_axis; + move32(); +#endif + hIvasDec->updateOrientation = true; move16(); @@ -2211,6 +2628,34 @@ static ivas_error copyRendererConfigStruct( Copy32( hRCin->roomAcoustics.pAcoustic_rt60_fx, hRCout->roomAcoustics.pAcoustic_rt60_fx, CLDFB_NO_CHANNELS_MAX ); // Q26 Copy32( hRCin->roomAcoustics.pAcoustic_dsr_fx, hRCout->roomAcoustics.pAcoustic_dsr_fx, CLDFB_NO_CHANNELS_MAX ); // Q30 Copy( hRCin->directivity_fx, hRCout->directivity_fx, 3 * MAX_NUM_OBJECTS ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + hRCout->split_rend_config.splitRendBitRate = SPLIT_REND_768k; + hRCout->split_rend_config.dof = 3; + hRCout->split_rend_config.hq_mode = 0; + hRCout->split_rend_config.codec_delay_ms = 0; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hRCout->split_rend_config.isar_frame_size_ms = 20; + move16(); +#endif + hRCout->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */ + hRCout->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + hRCout->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hRCout->split_rend_config.lc3plus_highres = hRCin->split_rend_config.lc3plus_highres; + move16(); +#endif + move32(); + move16(); + move16(); + move16(); + move16(); + move32(); + move32(); + move32(); +#endif + hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er; hRCout->roomAcoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity; move16(); @@ -2275,6 +2720,9 @@ ivas_error IVAS_DEC_FeedRenderConfig( ) { RENDER_CONFIG_HANDLE hRenderConfig; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_error error; +#endif test(); test(); @@ -2313,6 +2761,21 @@ ivas_error IVAS_DEC_FeedRenderConfig( Copy( renderConfig.directivity_fx, hRenderConfig->directivity_fx, 3 * MAX_NUM_OBJECTS ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + hRenderConfig->split_rend_config = renderConfig.split_rend_config; + + /* Overwrite any pose correction settings if 0 DOF (no pose correction) was selected */ + IF( hRenderConfig->split_rend_config.dof == 0 ) + { + hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + } + + IF( ( error = isar_split_rend_validate_config( &hRenderConfig->split_rend_config, ( hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0 ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif + return IVAS_ERR_OK; } @@ -2367,8 +2830,13 @@ ivas_error IVAS_DEC_GetDelay( } move32(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + nSamples[1] = NS2SA_FX2( hDecoderConfig->output_Fs, get_delay_fx( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbAnaDec[0], hDecoderConfig->output_config ) ); + move16(); +#else nSamples[1] = NS2SA_FX2( hDecoderConfig->output_Fs, get_delay_fx( DEC, hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->cldfbAnaDec[0] ) ); move16(); +#endif nSamples[2] = extract_l( W_round64_L( W_mult0_32_32( L_shl( st_ivas->binaural_latency_ns, 1 ), out_fs_fx ) ) ); move16(); nSamples[0] = add( nSamples[1], nSamples[2] ); @@ -3265,7 +3733,11 @@ static ivas_error printConfigInfo_dec( test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else IF( ( EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( (Word16) output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) +#endif { fprintf( stdout, "Render framesize: %dms\n", get_render_frame_size_ms( st_ivas->hDecoderConfig->render_framesize ) ); } @@ -3658,3 +4130,214 @@ static ivas_error IVAS_DEC_VoIP_reconfigure( return IVAS_ERR_OK; } + + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*---------------------------------------------------------------------* + * IVAS_DEC_GetSplitRendBitstreamHeader() + * + * + *---------------------------------------------------------------------*/ + +ivas_error +IVAS_DEC_GetSplitRendBitstreamHeader( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */ + ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 *pIsar_frame_size_ms, /* o: pointer to isar frame size setting */ +#endif + Word16 *pCodec_frame_size_ms /* o: pointer to codec frame size setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + Word16 *pLc3plusHighRes +#endif +) +{ + if ( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + *pCodec = hIvasDec->st_ivas->hRenderConfig->split_rend_config.codec; + *pCodec_frame_size_ms = hIvasDec->st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms; + *poseCorrection = hIvasDec->st_ivas->hRenderConfig->split_rend_config.poseCorrectionMode; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + *pIsar_frame_size_ms = hIvasDec->st_ivas->hRenderConfig->split_rend_config.isar_frame_size_ms; + *pLc3plusHighRes = hIvasDec->st_ivas->hRenderConfig->split_rend_config.lc3plus_highres; +#endif + return IVAS_ERR_OK; +} + + +/*---------------------------------------------------------------------* + * IVAS_DEC_GetCldfbSamples() + * + * API function to output CLDFB samples + *---------------------------------------------------------------------*/ + +ivas_error IVAS_DEC_GetCldfbSamples( + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + Word32 *out_real, /* o : buffer for decoded PCM real output in CLDFB domain */ + Word32 *out_imag, /* o : buffer for decoded PCM imag output in CLDFB domain */ + AUDIO_CONFIG *audio_config, /* o : audio configuration */ + Word16 *nOutSamples /* o : number of samples per channel written to output buffer */ +) +{ + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; + Word16 ch, b, slot_idx, num_chs, maxBand, num_samples; + + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL || hIvasDec->st_ivas->hSplitBinRend == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + + hSplitBinRend = hIvasDec->st_ivas->hSplitBinRend; + num_samples = 0; + + IF( hSplitBinRend->hCldfbDataOut != NULL ) + { + *audio_config = hSplitBinRend->hCldfbDataOut->config; + IF( hSplitBinRend->hCldfbDataOut->config != IVAS_AUDIO_CONFIG_INVALID ) + { + num_chs = audioCfg2channels( hSplitBinRend->hCldfbDataOut->config ); + maxBand = (int16_t) ( ( CLDFB_NO_CHANNELS_MAX * hIvasDec->st_ivas->hDecoderConfig->output_Fs ) / 48000 ); + + FOR( slot_idx = 0; slot_idx < CLDFB_NO_COL_MAX; slot_idx++ ) + { + FOR( b = 0; b < maxBand; b++ ) + { + FOR( ch = 0; ch < num_chs; ch++ ) + { + *out_real++ = hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer_fx[ch][slot_idx][b]; + *out_imag++ = hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer_fx[ch][slot_idx][b]; + } + } + } + num_samples = CLDFB_NO_COL_MAX * maxBand; + } + } + ELSE + { + *audio_config = IVAS_AUDIO_CONFIG_INVALID; + } + + *nOutSamples = num_samples; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_create_handle_isar() + * + * Initialize IVAS decoder split rend handle + *-------------------------------------------------------------------*/ + +static ivas_error ivas_create_handle_isar( + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE *hSplitBinRend_out /* o : ISAR split binaural rendering handle */ +) +{ + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE hSplitBinRend; + + if ( ( hSplitBinRend = (ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE) malloc( sizeof( ISAR_DEC_SPLIT_REND_WRAPPER ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS decoder handle" ); + } + + isar_init_split_rend_handles( &hSplitBinRend->splitrend ); + + hSplitBinRend->hMultiBinCldfbData = NULL; + hSplitBinRend->hCldfbDataOut = NULL; + hSplitBinRend->numTdSamplesPerChannelCached = 0; + + *hSplitBinRend_out = hSplitBinRend; + + return IVAS_ERR_OK; +} + + +/*-------------------------------------------------------------------* + * ivas_destroy_handle_isar() + * + * destroy IVAS decoder split rend handle + *-------------------------------------------------------------------*/ + +static void ivas_destroy_handle_isar( + ISAR_DEC_SPLIT_REND_WRAPPER_HANDLE *hSplitBinRend /* i/o: ISAR split binaural rendering handle */ +) +{ + IF( *hSplitBinRend != NULL ) + { + ISAR_PRE_REND_close( &( *hSplitBinRend )->splitrend, NULL ); + + IF( ( *hSplitBinRend )->hCldfbDataOut != NULL ) + { + free( ( *hSplitBinRend )->hCldfbDataOut ); + ( *hSplitBinRend )->hCldfbDataOut = NULL; + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * IVAS_DEC_is_split_rendering_enabled() + * + * + *---------------------------------------------------------------------*/ + +int16_t IVAS_DEC_is_split_rendering_enabled( + IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +) +{ + Decoder_Struct *st_ivas; + Word16 isSplitRend; + + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + st_ivas = hIvasDec->st_ivas; + isSplitRend = 0; + + IF( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || + ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO && st_ivas->hDecoderConfig->Opt_non_diegetic_pan && st_ivas->hRenderConfig->split_rend_config.dof == 0 ) ) + { + isSplitRend = 1; + } + + return isSplitRend; +} + + +/*---------------------------------------------------------------------* + * IVAS_DEC_is_split_rendering_coded_out() + * + * + *---------------------------------------------------------------------*/ + +Word16 IVAS_DEC_is_split_rendering_coded_out( + IVAS_DEC_HANDLE hIvasDec /* i/o: IVAS decoder handle */ +) +{ + Decoder_Struct *st_ivas; + Word16 isSplitCoded; + + IF( hIvasDec == NULL || hIvasDec->st_ivas == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + st_ivas = hIvasDec->st_ivas; + isSplitCoded = 0; + + IF( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || + ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO && st_ivas->hDecoderConfig->Opt_non_diegetic_pan && st_ivas->hRenderConfig->split_rend_config.dof == 0 ) ) + { + isSplitCoded = 1; + } + + return isSplitCoded; +} +#endif diff --git a/lib_isar/isar_stat.h b/lib_isar/isar_stat.h index 4c3dd12e1..5487cf071 100644 --- a/lib_isar/isar_stat.h +++ b/lib_isar/isar_stat.h @@ -256,7 +256,7 @@ typedef struct ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE hSplitBinLCLDEnc; CLDFB_HANDLES_WRAPPER_HANDLE hCldfbHandles; ISAR_LC3PLUS_ENC_HANDLE hLc3plusEnc; - float *lc3plusDelayBuffers[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* Used to time-align head pose correction metadata with LC3plus-coded reference audio */ + // float *lc3plusDelayBuffers[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* Used to time-align head pose correction metadata with LC3plus-coded reference audio */ Word32 *lc3plusDelayBuffers_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* Used to time-align head pose correction metadata with LC3plus-coded reference audio */ Word16 lc3plusDelayBuffers_q; Word32 lc3plusDelaySamples; diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 2149d2225..447fed0ba 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -273,11 +273,6 @@ void ISAR_PRE_REND_close( FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) { - IF( hSplitBinRend->lc3plusDelayBuffers[i] != NULL ) - { - free( hSplitBinRend->lc3plusDelayBuffers[i] ); - hSplitBinRend->lc3plusDelayBuffers[i] = NULL; - } if ( hSplitBinRend->lc3plusDelayBuffers_fx[i] != NULL ) { free( hSplitBinRend->lc3plusDelayBuffers_fx[i] ); @@ -288,10 +283,10 @@ void ISAR_PRE_REND_close( IF( pSplitRendEncBuffer != NULL ) { - IF( pSplitRendEncBuffer->data != NULL ) + IF( pSplitRendEncBuffer->data_fx != NULL ) { - free( pSplitRendEncBuffer->data ); - pSplitRendEncBuffer->data = NULL; + free( pSplitRendEncBuffer->data_fx ); + pSplitRendEncBuffer->data_fx = NULL; } pSplitRendEncBuffer->config.numChannels = 0; @@ -335,7 +330,6 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const Word16 max_bands, - float *output[], Word32 *pOutput_fx[], const Word16 low_res_pre_rend_rot, const Word16 cldfb_in_flag, @@ -361,7 +355,6 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( FILE *fp = fopen( "Float_code_output.txt", "ab+" ); FILE *fp1 = fopen( "Float_code_cldfb_state.txt", "ab+" );*/ #endif - output; Q_buff_re = Q_buff; move16(); Q_buff_im = Q_buff; diff --git a/lib_isar/lib_isar_pre_rend.h b/lib_isar/lib_isar_pre_rend.h index fe64e4911..928fb001d 100644 --- a/lib_isar/lib_isar_pre_rend.h +++ b/lib_isar/lib_isar_pre_rend.h @@ -79,7 +79,6 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Word32 Cldfb_In_BinReal_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB real buffer */ Word32 Cldfb_In_BinImag_fx[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: CLDFB imag buffer */ const Word16 max_bands, /* i: CLDFB bands */ - float *output[], /* i/o: PCM in/out buffer */ Word32 *pOutput_fx[], /* i: low time resolution pre-renderer flag */ const Word16 low_res_pre_rend_rot, /* i: low time resolution pre-renderer flag */ const Word16 cldfb_in_flag, /* i: Flag to indicate CLDFB or time doamin input */ -- GitLab From 3bd4f5e7013cb54f409ff570d62427c311ee468e Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 30 Jan 2025 02:03:44 +1100 Subject: [PATCH 04/43] lib rend changes --- lib_com/ivas_prot_fx.h | 19 + lib_com/ivas_rotation_com.c | 73 + lib_dec/ivas_binRenderer_internal.c | 13 +- lib_enc/lib_enc.c | 5 + lib_isar/isar_stat.h | 8 - lib_rend/ivas_crend.c | 703 ++++++- lib_rend/ivas_dirac_dec_binaural_functions.c | 1713 +++++++++++++++--- lib_rend/ivas_prot_rend.h | 121 +- lib_rend/ivas_stat_rend.h | 56 +- 9 files changed, 2359 insertions(+), 352 deletions(-) diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 5849bf97d..0fd85daae 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -5938,6 +5938,25 @@ void Quat2EulerDegree_fx( Word32 *pitch_fx, /* o : pitch */ Word32 *roll_fx /* o : roll */ ); + +void Copy_Quat_fx( + const IVAS_QUATERNION *in_quat, /* i : quaternion describing the rotation */ + IVAS_QUATERNION *out_quat /* i : quaternion describing the rotation */ +); + +void modify_Quat_q_fx( + const IVAS_QUATERNION *in_quat, /* i : quaternion describing the rotation */ + IVAS_QUATERNION *out_quat, /* i : quaternion describing the rotation */ + Word16 q_new /* i : quaternion describing the rotation */ +); + +void modify_Rmat_q_fx( + const Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ + Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ + Word16 num_subframes, + Word16 q_cur, /* i : current q factor for rotation matrix */ + Word16 q_new /* i : target q factor for rotation matrix */ +); #endif #endif diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index 20eaf6188..9e5d1a594 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -96,6 +96,79 @@ void Euler2Quat( #ifdef SPLIT_REND_WITH_HEAD_ROT + +/*------------------------------------------------------------------------- + * Copy_Quat_fx() + * + * Quaternion q factor modification + *------------------------------------------------------------------------*/ +void Copy_Quat_fx( + const IVAS_QUATERNION *in_quat, /* i : quaternion describing the rotation */ + IVAS_QUATERNION *out_quat /* i : quaternion describing the rotation */ +) +{ + out_quat->q_fact = in_quat->q_fact; + out_quat->w_fx = in_quat->w_fx; + out_quat->x_fx = in_quat->x_fx; + out_quat->y_fx = in_quat->y_fx; + out_quat->z_fx = in_quat->z_fx; + move16(); + move32(); + move32(); + move32(); + move32(); + + return; +} + +/*------------------------------------------------------------------------- + * Scale_Quat_fx() + * + * Quaternion q factor modification + *------------------------------------------------------------------------*/ +void modify_Quat_q_fx( + const IVAS_QUATERNION *in_quat, /* i : quaternion describing the rotation */ + IVAS_QUATERNION *out_quat, /* i : quaternion describing the rotation */ + Word16 q_new /* i : quaternion describing the rotation */ +) +{ + out_quat->w_fx = L_shl( in_quat->w_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->x_fx = L_shl( in_quat->x_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->y_fx = L_shl( in_quat->y_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->z_fx = L_shl( in_quat->z_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->q_fact = q_new; + return; +} + +/*------------------------------------------------------------------------- + * modify_Rmat_q_fx() + * + * Rotation matrix q factor modification + *------------------------------------------------------------------------*/ +void modify_Rmat_q_fx( + const Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ + Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ + Word16 num_subframes, + Word16 q_cur, /* i : current q factor for rotation matrix */ + Word16 q_new /* i : target q factor for rotation matrix */ +) +{ + Word16 i, j, k; + + FOR( i = 0; i < num_subframes; i++ ) + { + FOR( j = 0; j < 3; j++ ) + { + FOR( k = 0; k < 3; k++ ) + { + Rmat_out[i][j][k] = L_shl( Rmat_in[i][j][k], sub( q_new, q_cur ) ); + move32(); + } + } + } + return; +} + /*------------------------------------------------------------------------- * Quat2EulerDegree() * diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 913b7c366..040d9bf9d 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1945,10 +1945,7 @@ void ivas_binRenderer_fx( Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 q_fact_orig = Quaternions_ref->q_fact; - Quaternions_ref->w_fx = L_shl( Quaternions_ref->w_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 - Quaternions_ref->x_fx = L_shl( Quaternions_ref->x_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 - Quaternions_ref->y_fx = L_shl( Quaternions_ref->y_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 - Quaternions_ref->z_fx = L_shl( Quaternions_ref->z_fx, sub( Q22, Quaternions_ref->q_fact ) ); // Q22 + modify_Quat_q_fx( Quaternions_ref, Quaternions_ref, Q22 ); IF( EQ_16( hCombinedOrientationData->shd_rot_max_order, 0 ) ) { @@ -1981,13 +1978,13 @@ void ivas_binRenderer_fx( Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, Quaternions_rel.z_fx ); Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), deg2rad_fx( Quaternions_abs.y_fx ), deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs ); - Quaternions_abs.w_fx = L_shl( Quaternions_abs.w_fx, Q7 ); // Q29 - Quaternions_abs.x_fx = L_shl( Quaternions_abs.x_fx, Q7 ); // Q29 - Quaternions_abs.y_fx = L_shl( Quaternions_abs.y_fx, Q7 ); // Q29 - Quaternions_abs.z_fx = L_shl( Quaternions_abs.z_fx, Q7 ); // Q29 + + modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig ); QuatToRotMat_fx( Quaternions_abs, Rmat_local ); + modify_Rmat_q_fx( Rmat_local, Rmat_local, MAX_PARAM_SPATIAL_SUBFRAMES, sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); + if ( hBinRenderer->hInputSetup->is_loudspeaker_setup ) { rotateFrame_sd_cldfb( Rmat_local, RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); diff --git a/lib_enc/lib_enc.c b/lib_enc/lib_enc.c index c78fbe107..8227d45dd 100644 --- a/lib_enc/lib_enc.c +++ b/lib_enc/lib_enc.c @@ -1447,8 +1447,13 @@ ivas_error IVAS_ENC_GetDelay( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + *delay = NS2SA( hEncoderConfig->input_Fs, get_delay_fx( ENC, hEncoderConfig->input_Fs, hEncoderConfig->ivas_format, NULL, IVAS_AUDIO_CONFIG_INVALID ) ); + move16(); +#else *delay = NS2SA( hEncoderConfig->input_Fs, get_delay_fx( ENC, hEncoderConfig->input_Fs, hEncoderConfig->ivas_format, NULL ) ); move16(); +#endif *delay = imult1616( *delay, hEncoderConfig->nchan_inp ); move16(); diff --git a/lib_isar/isar_stat.h b/lib_isar/isar_stat.h index 5487cf071..228bc94df 100644 --- a/lib_isar/isar_stat.h +++ b/lib_isar/isar_stat.h @@ -136,14 +136,6 @@ typedef struct isar_binaural_head_rot_split_pre_rendering_struct float fix_pos_rot_mat[MAX_HEAD_ROT_POSES - 1][BINAURAL_CHANNELS][BINAURAL_CHANNELS]; ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1]; ISAR_BIN_HR_SPLIT_REND_HUFF huff_cfg; -#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG - HANDLE_CLDFB_FILTER_BANK cldfbSynRotBinDec[MAX_HEAD_ROT_POSES + 1][BINAURAL_CHANNELS]; -#endif - -#ifdef SPLIT_POSE_CORRECTION_DEBUG - BIN_HR_SPLIT_POST_REND_HANDLE hBinHrSplitPostRend; -#endif - } ISAR_BIN_HR_SPLIT_PRE_REND, *ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE; /*----------------------------------------------------------------------------------* * Output configuration for renderer (e.g. DirAC, MASA, Binaural Renderer...) diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index d8cfec1d1..4a4cce092 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -193,7 +193,11 @@ static ivas_error ivas_rend_initCrend_fx( test(); test(); - IF( NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + IF( NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Encountered unsupported output type in Crend" ); } @@ -1397,10 +1401,19 @@ static ivas_error ivas_er_init_handle( *------------------------------------------------------------------------*/ ivas_error ivas_rend_initCrendWrapper( - CREND_WRAPPER_HANDLE *pCrend ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + CREND_WRAPPER_HANDLE *pCrend, + const int16_t num_poses +#else + CREND_WRAPPER_HANDLE *pCrend +#endif +) { Word16 i; CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif IF( pCrend == NULL ) { @@ -1416,6 +1429,9 @@ ivas_error ivas_rend_initCrendWrapper( move32(); ( *pCrend )->hHrtfCrend = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) +#endif { hCrend = NULL; IF( ( hCrend = (CREND_HANDLE) malloc( sizeof( CREND_DATA ) ) ) == NULL ) @@ -1452,12 +1468,44 @@ ivas_error ivas_rend_initCrendWrapper( move32(); move32(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( *pCrend )->hCrend[pos_idx] = hCrend; +#else ( *pCrend )->hCrend = hCrend; +#endif } return IVAS_ERR_OK; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*------------------------------------------------------------------------- + * ivas_rend_openMultiBinCrend() + * + * Allocate and initialize crend renderer handle + *------------------------------------------------------------------------*/ + +ivas_error ivas_rend_openMultiBinCrend( + CREND_WRAPPER_HANDLE *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word32 output_Fs ) +{ + ivas_error error; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( ( error = ivas_rend_openCrend( pCrend, inConfig, outConfig, NULL /*hRendCfg*/, NULL, output_Fs, pMultiBinPoseData->num_poses ) ) != IVAS_ERR_OK ) +#else + if ( ( error = ivas_rend_openCrend( pCrend, inConfig, outConfig, NULL /*hRendCfg*/, NULL, output_Fs ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + + return error; +} +#endif /*------------------------------------------------------------------------- * ivas_rend_openCrend() @@ -1471,156 +1519,182 @@ ivas_error ivas_rend_openCrend( const AUDIO_CONFIG outConfig, RENDER_CONFIG_DATA *hRendCfg, HRTFS_CREND_HANDLE hSetOfHRTF, - const Word32 output_Fs ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word32 output_Fs, + const Word16 num_poses +#else + const Word32 output_Fs +#endif +) { Word16 i, subframe_length; Word16 max_total_ir_len; HRTFS_HANDLE hHrtf; CREND_HANDLE hCrend; ivas_error error; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif error = IVAS_ERR_OK; move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( error = ivas_rend_initCrendWrapper( pCrend, num_poses ) ) != IVAS_ERR_OK ) +#else IF( NE_32( ( error = ivas_rend_initCrendWrapper( pCrend ) ), IVAS_ERR_OK ) ) +#endif { return error; } subframe_length = extract_l( Mult_32_16( output_Fs, 164 ) ); /*( output_Fs / FRAMES_PER_SEC ) / MAX_PARAM_SPATIAL_SUBFRAMES(i/o:164=(32768/FRAMES_PER_SEC)/MAX_PARAM_SPATIAL_SUBFRAMES*/ - IF( ( *pCrend )->hHrtfCrend == NULL ){ - IF( NE_32( ( error = ivas_rend_initCrend_fx( *pCrend, inConfig, outConfig, hSetOfHRTF, output_Fs ) ), IVAS_ERR_OK ) ){ + IF( ( *pCrend )->hHrtfCrend == NULL ) + { + IF( NE_32( ( error = ivas_rend_initCrend_fx( *pCrend, inConfig, outConfig, hSetOfHRTF, output_Fs ) ), IVAS_ERR_OK ) ) + { return error; -} -} - -{ - hCrend = ( *pCrend )->hCrend; - hHrtf = ( *pCrend )->hHrtfCrend; + } + } - IF( hHrtf != NULL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) +#endif { - max_total_ir_len = imult1616( hHrtf->max_num_iterations, subframe_length ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = ( *pCrend )->hCrend[pos_idx]; +#else + hCrend = ( *pCrend )->hCrend; +#endif + hHrtf = ( *pCrend )->hHrtfCrend; - FOR( i = 0; i < hHrtf->max_num_ir; i++ ) + IF( hHrtf != NULL ) { - IF( ( hCrend->freq_buffer_re_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); - } - set_zero_fx( hCrend->freq_buffer_re_fx[i], max_total_ir_len ); - IF( ( hCrend->freq_buffer_im_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + max_total_ir_len = imult1616( hHrtf->max_num_iterations, subframe_length ); + + FOR( i = 0; i < hHrtf->max_num_ir; i++ ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + IF( ( hCrend->freq_buffer_re_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero_fx( hCrend->freq_buffer_re_fx[i], max_total_ir_len ); + IF( ( hCrend->freq_buffer_im_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero_fx( hCrend->freq_buffer_im_fx[i], max_total_ir_len ); } - set_zero_fx( hCrend->freq_buffer_im_fx[i], max_total_ir_len ); - } - FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) - { - IF( ( hCrend->prev_out_buffer_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * subframe_length ) ) == NULL ) + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + IF( ( hCrend->prev_out_buffer_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * subframe_length ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero_fx( hCrend->prev_out_buffer_fx[i], subframe_length ); } - set_zero_fx( hCrend->prev_out_buffer_fx[i], subframe_length ); - } - max_total_ir_len = imult1616( (Word16) hHrtf->num_iterations_diffuse[0], subframe_length ); + max_total_ir_len = imult1616( (Word16) hHrtf->num_iterations_diffuse[0], subframe_length ); - IF( max_total_ir_len > 0 ) - { - IF( ( hCrend->freq_buffer_re_diffuse_fx = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + IF( max_total_ir_len > 0 ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + IF( ( hCrend->freq_buffer_re_diffuse_fx = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero_fx( hCrend->freq_buffer_re_diffuse_fx, max_total_ir_len ); + IF( ( hCrend->freq_buffer_im_diffuse_fx = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero_fx( hCrend->freq_buffer_im_diffuse_fx, max_total_ir_len ); } - set_zero_fx( hCrend->freq_buffer_re_diffuse_fx, max_total_ir_len ); - IF( ( hCrend->freq_buffer_im_diffuse_fx = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + ELSE { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + hCrend->freq_buffer_re_diffuse_fx = NULL; + hCrend->freq_buffer_im_diffuse_fx = NULL; } - set_zero_fx( hCrend->freq_buffer_im_diffuse_fx, max_total_ir_len ); - } - ELSE - { - hCrend->freq_buffer_re_diffuse_fx = NULL; - hCrend->freq_buffer_im_diffuse_fx = NULL; - } - max_total_ir_len = add( extract_l( L_shr( L_add( L_shl( Mult_32_32( hHrtf->latency_s_fx, output_Fs ), 1 ), 1 ), 1 ) ), subframe_length ); /*(int16_t) ( hHrtf->latency_s * output_Fs + 0.5f ) + subframe_length;*/ - IF( max_total_ir_len > 0 ) - { - IF( ( hCrend->lfe_delay_line_fx = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + max_total_ir_len = add( extract_l( L_shr( L_add( L_shl( Mult_32_32( hHrtf->latency_s_fx, output_Fs ), 1 ), 1 ), 1 ) ), subframe_length ); /*(int16_t) ( hHrtf->latency_s * output_Fs + 0.5f ) + subframe_length;*/ + IF( max_total_ir_len > 0 ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + IF( ( hCrend->lfe_delay_line_fx = (Word32 *) malloc( sizeof( Word32 ) * max_total_ir_len ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Crend" ); + } + set_zero_fx( hCrend->lfe_delay_line_fx, max_total_ir_len ); } - set_zero_fx( hCrend->lfe_delay_line_fx, max_total_ir_len ); - } - ELSE - { - hCrend->lfe_delay_line_fx = NULL; - } - - IF( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) - { - IF( NE_32( ( error = ivas_reverb_open_fx( &( hCrend->hReverb ), inConfig, ( *pCrend )->hHrtfCrend, NULL, hRendCfg, output_Fs ) ), IVAS_ERR_OK ) ) + ELSE { - return error; + hCrend->lfe_delay_line_fx = NULL; } - IF( EQ_16( hRendCfg->roomAcoustics.use_er, 1 ) ) + IF( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) { - - /* Allocate memory for reflections */ - hCrend->reflections = (er_struct_t *) malloc( sizeof( er_struct_t ) ); - IF( !hCrend->reflections ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections" ); - } - IF( NE_32( ( error = ivas_er_init_handle( hCrend->reflections ) ), IVAS_ERR_OK ) ) + IF( NE_32( ( error = ivas_reverb_open_fx( &( hCrend->hReverb ), inConfig, ( *pCrend )->hHrtfCrend, NULL, hRendCfg, output_Fs ) ), IVAS_ERR_OK ) ) { return error; } - hCrend->reflections->use_er = hRendCfg->roomAcoustics.use_er; - hCrend->reflections->lowComplexity = hRendCfg->roomAcoustics.lowComplexity; - move16(); - move32(); + IF( EQ_16( hRendCfg->roomAcoustics.use_er, 1 ) ) + { - /* Set sample rate and frame size */ + /* Allocate memory for reflections */ + hCrend->reflections = (er_struct_t *) malloc( sizeof( er_struct_t ) ); + IF( !hCrend->reflections ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Early Reflections" ); + } + IF( NE_32( ( error = ivas_er_init_handle( hCrend->reflections ) ), IVAS_ERR_OK ) ) + { + return error; + } - hCrend->reflections->output_Fs_fx = output_Fs; // Q0 - move32(); + hCrend->reflections->use_er = hRendCfg->roomAcoustics.use_er; + hCrend->reflections->lowComplexity = hRendCfg->roomAcoustics.lowComplexity; + move16(); + move32(); - hCrend->reflections->max_frame_size = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) ); - move32(); + /* Set sample rate and frame size */ + + hCrend->reflections->output_Fs_fx = output_Fs; // Q0 + move32(); + + hCrend->reflections->max_frame_size = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) ); + move32(); - /* Init Shoebox */ - ivas_shoebox_config_init( &hCrend->reflections->shoebox_lib.cal, hRendCfg ); + /* Init Shoebox */ + ivas_shoebox_config_init( &hCrend->reflections->shoebox_lib.cal, hRendCfg ); - /* Init and compute Reflections */ - IF( NE_32( ( error = ivas_er_init( hCrend->reflections, inConfig ) ), IVAS_ERR_OK ) ) + /* Init and compute Reflections */ + IF( NE_32( ( error = ivas_er_init( hCrend->reflections, inConfig ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE { - return error; + hCrend->reflections = NULL; } } ELSE { - hCrend->reflections = NULL; + hCrend->hReverb = NULL; } - } - ELSE - { - hCrend->hReverb = NULL; + + ( *pCrend )->binaural_latency_ns = Mult_32_32( ( *pCrend )->hHrtfCrend->latency_s_fx, (Word32) 1000000000 ); + move32(); } - ( *pCrend )->binaural_latency_ns = Mult_32_32( ( *pCrend )->hHrtfCrend->latency_s_fx, (Word32) 1000000000 ); - move32(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( *pCrend )->hCrend[pos_idx] = hCrend; +#else + ( *pCrend )->hCrend = hCrend; +#endif } - - ( *pCrend )->hCrend = hCrend; -} -return IVAS_ERR_OK; + return IVAS_ERR_OK; } /*------------------------------------------------------------------------- @@ -1630,9 +1704,18 @@ return IVAS_ERR_OK; *------------------------------------------------------------------------*/ void ivas_rend_closeCrend( - CREND_WRAPPER_HANDLE *pCrend ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + CREND_WRAPPER_HANDLE *pCrend, + const Word16 num_poses +#else + CREND_WRAPPER_HANDLE *pCrend +#endif +) { Word16 i; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif CREND_HANDLE hCrend; test(); @@ -1646,8 +1729,15 @@ void ivas_rend_closeCrend( ivas_hrtf_close( &( *pCrend )->hHrtfCrend ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) +#endif { +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = ( *pCrend )->hCrend[pos_idx]; +#else hCrend = ( *pCrend )->hCrend; +#endif IF( hCrend != NULL ) { FOR( i = 0; i < MAX_INTERN_CHANNELS; i++ ) @@ -1714,7 +1804,11 @@ void ivas_rend_closeCrend( } free( hCrend ); hCrend = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( *pCrend )->hCrend[pos_idx] = hCrend; +#else ( *pCrend )->hCrend = hCrend; +#endif } } @@ -1725,6 +1819,30 @@ void ivas_rend_closeCrend( } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*------------------------------------------------------------------------- + * ivas_rend_closeCldfbRend() + * + * Close CLDFB based fastconv binaural renderer memories + *------------------------------------------------------------------------*/ + +void ivas_rend_closeCldfbRend( + CLDFB_REND_WRAPPER *pCldfbRend ) +{ + IF( pCldfbRend->hCldfbRend->hInputSetup != NULL ) + { + free( pCldfbRend->hCldfbRend->hInputSetup ); + pCldfbRend->hCldfbRend->hInputSetup = NULL; + } + + ivas_binRenderer_close( &pCldfbRend->hCldfbRend ); + ivas_binaural_hrtf_close( &pCldfbRend->hHrtfFastConv ); + ivas_HRTF_fastconv_binary_close( &pCldfbRend->hHrtfFastConv ); + + return; +} +#endif + /*-----------------------------------------------------------------------------------------* * Function ivas_rend_crendConvolver() * @@ -1738,7 +1856,13 @@ static ivas_error ivas_rend_crendConvolver( Word32 *pcm_in[], // Qx Word32 *pcm_out[], // Qx const Word32 output_Fs, - const Word16 i_ts ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 i_ts, + const Word16 pos_idx +#else + const Word16 i_ts +#endif +) { Word16 i, j, k, m; Word16 subframe_length, idx_in; @@ -1755,7 +1879,11 @@ static ivas_error ivas_rend_crendConvolver( ivas_error error; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = pCrend->hCrend[pos_idx]; +#else hCrend = pCrend->hCrend; +#endif IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &nchan_in ) ), IVAS_ERR_OK ) ) { @@ -1933,7 +2061,12 @@ ivas_error ivas_rend_crendProcess( EFAP_HANDLE hEFAPdata, Word32 *output_fx[], /* i/o: input/output audio channels Qx */ const Word32 output_Fs, +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 num_subframes /* i : number of subframes to render */, + const Word16 pos_idx +#else const Word16 num_subframes /* i : number of subframes to render */ +#endif ) { Word16 i, subframe_idx, subframe_len; @@ -1945,7 +2078,11 @@ ivas_error ivas_rend_crendProcess( ivas_error error; CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = pCrend->hCrend[pos_idx]; +#else hCrend = pCrend->hCrend; +#endif combinedOrientationEnabled = 0; move16(); @@ -2039,15 +2176,22 @@ ivas_error ivas_rend_crendProcess( test(); IF( EQ_16( inConfigType, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) || EQ_16( inConfigType, IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ) { - +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendConvolver( pCrend, inConfig, outConfig, output_fx, p_pcm_tmp_fx, output_Fs, subframe_idx, pos_idx ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendConvolver( pCrend, inConfig, outConfig, output_fx, p_pcm_tmp_fx, output_Fs, subframe_idx ) ), IVAS_ERR_OK ) ) +#endif { return error; } IF( hCrend->hReverb != NULL ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_reverb_process_fx( pCrend->hCrend[pos_idx]->hReverb, inConfig, 1, output_fx, p_pcm_tmp_fx, subframe_idx ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_reverb_process_fx( pCrend->hCrend->hReverb, inConfig, 1, output_fx, p_pcm_tmp_fx, subframe_idx ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -2090,6 +2234,10 @@ ivas_error ivas_rend_crendProcessSubframe( Word32 *output[], /* i/o: input/output audio channels Qx */ const Word16 n_samples_to_render, /* i : output frame length per channel */ const Word32 output_Fs /* i : output sampling rate */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + , + const Word16 pos_idx +#endif ) { Word16 subframe_idx, subframe_len; @@ -2101,7 +2249,11 @@ ivas_error ivas_rend_crendProcessSubframe( ivas_error error; Word8 combinedOrientationEnabled; CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = pCrend->hCrend[pos_idx]; +#else hCrend = pCrend->hCrend; +#endif combinedOrientationEnabled = 0; move16(); @@ -2190,13 +2342,24 @@ ivas_error ivas_rend_crendProcessSubframe( test(); IF( EQ_32( inConfigType, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) || EQ_32( inConfigType, IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ) { - +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendConvolver( pCrend, inConfig, outConfig, tc_local_fx, p_pcm_tmp_fx, output_Fs, 0, pos_idx ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendConvolver( pCrend, inConfig, outConfig, tc_local_fx, p_pcm_tmp_fx, output_Fs, 0 ) ), IVAS_ERR_OK ) ) - +#endif { return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( pCrend->hCrend[0]->hReverb != NULL ) + { + IF( NE_32( ( error = ivas_reverb_process_fx( pCrend->hCrend[pos_idx]->hReverb, inConfig, 1, tc_local_fx, p_pcm_tmp_fx, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } + } +#else IF( pCrend->hCrend->hReverb != NULL ) { IF( NE_32( ( error = ivas_reverb_process_fx( pCrend->hCrend->hReverb, inConfig, 1, tc_local_fx, p_pcm_tmp_fx, 0 ) ), IVAS_ERR_OK ) ) @@ -2204,6 +2367,7 @@ ivas_error ivas_rend_crendProcessSubframe( return error; } } +#endif FOR( ch = 0; ch < nchan_in; ch++ ) { tc_local_fx[ch] += subframe_len; @@ -2222,7 +2386,12 @@ ivas_error ivas_rend_crendProcessSubframe( /* update combined orientation access index */ ivas_combined_orientation_update_index( hCombinedOrientationData, subframe_len ); } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( pCrend->hCrend[0]->hReverb != NULL ) +#else IF( pCrend->hCrend->hReverb != NULL ) +#endif { *pCrend->p_io_qfactor = sub( *pCrend->p_io_qfactor, 2 ); move16(); @@ -2247,3 +2416,339 @@ ivas_error ivas_rend_crendProcessSubframe( return IVAS_ERR_OK; } + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-----------------------------------------------------------------------------------------* + * Function ivas_rend_crend_ProcessSplitBin() + * + * Process call for IVAS Crend renderer + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_rend_crendProcessSplitBin( + const CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const DECODER_CONFIG_HANDLE hDecoderConfig, + const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, + const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, + EFAP_HANDLE hEFAPdata, + Word32 *output[], + const Word32 output_Fs ) +{ + Word16 i, j; + Word16 sf; + Word16 pos_idx, output_frame; + ivas_error error; + Word32 gain_lfe; + Word32 tmpLfeBuffer[L_FRAME48k]; + Word32 tmpInputBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word32 *p_tmpInputBuffer[MAX_OUTPUT_CHANNELS]; + Word32 tmpSplitBinBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + COMBINED_ORIENTATION_DATA combinedOrientationDataLocal; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal; + + output_frame = extract_l( Mpy_32_32( output_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ); + + /* copy input */ + FOR( i = 0; i < hIntSetup->nchan_out_woLFE; ++i ) + { + Copy32( output[i], tmpInputBuffer[i], output_frame ); + } + + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) + { + p_tmpInputBuffer[i] = tmpInputBuffer[i]; + move32(); + } + + /* save current head positions */ + pCombinedOrientationDataLocal = hCombinedOrientationData; + move32(); + combinedOrientationDataLocal = *pCombinedOrientationDataLocal; + move32(); + IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + { + FOR( sf = 1; sf < hCombinedOrientationData->num_subframes; ++sf ) + { + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[0], &combinedOrientationDataLocal.Quaternions[sf] ); + FOR( i = 0; i < 3; i++ ) + { + FOR( j = 0; j < 3; j++ ) + { + combinedOrientationDataLocal.Rmat_fx[sf][i][j] = combinedOrientationDataLocal.Rmat_fx[0][i][j]; + move32(); + } + } + } + } + + /* copy LFE to tmpLfeBuffer and apply gain only once */ + IF( GT_16( hIntSetup->num_lfe, 0 ) && NE_16( hIntSetup->index_lfe[0], -1 ) ) + { + Copy32( output[hIntSetup->index_lfe[0]], tmpLfeBuffer, output_frame ); + gain_lfe = ( ( pCrend != NULL ) && ( pCrend->hHrtfCrend != NULL ) ) ? pCrend->hHrtfCrend->gain_lfe_fx : GAIN_LFE_FX; + v_multc_fixed_16( tmpLfeBuffer, gain_lfe, tmpLfeBuffer, output_frame ); // q_input_fx - 1 + Scale_sig32( tmpLfeBuffer, output_frame, 1 ); // q_input_fx + } + ELSE + { + set32_fx( tmpLfeBuffer, 0, output_frame ); + } + + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; ++pos_idx ) + { + /* Update head positions */ + + IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; + FOR( i = 0; i < hCombinedOrientationData->num_subframes; i++ ) + { + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] ); + Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 + move32(); + modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 ); + Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + + Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + combinedOrientationDataLocal.Quaternions[i] = Quaternions_abs; + move32(); + move32(); + move32(); + move32(); + modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Quaternions_orig[i].q_fact ); + QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + } + modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx, combinedOrientationDataLocal.Rmat_fx, MAX_PARAM_SPATIAL_SUBFRAMES, sub( shl( Quaternions_orig[0].q_fact, 1 ), 32 ), Q30 ); + + + /* render inplace to first two channels of tmpInputBuffer */ + pCombinedOrientationDataLocal = &combinedOrientationDataLocal; + move32(); + + FOR( i = 0; i < 3; i++ ) + { + Copy32( hCombinedOrientationData->Rmat_prev_fx[pos_idx][i], pCombinedOrientationDataLocal->Rmat_prev_fx[0][i], 3 ); + } + + IF( ( error = ivas_rend_crendProcessSubframe( pCrend, inConfig, outConfig, hDecoderConfig, pCombinedOrientationDataLocal, hIntSetup, hEFAPdata, + NULL, p_tmpInputBuffer, p_tmpInputBuffer, output_frame, output_Fs, pos_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + + FOR( i = 0; i < 3; i++ ) + { + Copy32( pCombinedOrientationDataLocal->Rmat_prev_fx[0][i], hCombinedOrientationData->Rmat_prev_fx[pos_idx][i], 3 ); + } + + FOR( i = 0; i < BINAURAL_CHANNELS; ++i ) + { + /* accumulate LFE to output */ + v_add_fx( tmpInputBuffer[i], tmpLfeBuffer, tmpInputBuffer[i], output_frame ); + + /* move to split bin output buffer */ + Copy32( tmpInputBuffer[i], tmpSplitBinBuffer[add( i_mult( pos_idx, BINAURAL_CHANNELS ), i )], output_frame ); + } + + /* overwrite rendered channels with input again for next iteration */ + FOR( i = 0; i < hIntSetup->nchan_out_woLFE; ++i ) + { + Copy32( output[i], tmpInputBuffer[i], output_frame ); + } + + /* restore original headrotation data */ + FOR( i = 0; i < hCombinedOrientationData->num_subframes; i++ ) + { + Copy_Quat_fx( &Quaternions_orig[i], &combinedOrientationDataLocal.Quaternions[i] ); + } + } + + /* copy split binaural rendered signals to final output */ + FOR( i = 0; i < BINAURAL_CHANNELS * pMultiBinPoseData->num_poses; ++i ) + { + Copy32( tmpSplitBinBuffer[i], output[i], output_frame ); + } + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------------------------* + * Function ivas_rend_crend_ProcessSubframesSplitBin() + * + * Process call for IVAS Crend renderer + *-----------------------------------------------------------------------------------------*/ + +ivas_error ivas_rend_crendProcessSubframesSplitBin( + const CREND_WRAPPER *pCrend, /* i/o: Crend wrapper handle */ + const AUDIO_CONFIG inConfig, /* i : input audio configuration */ + const AUDIO_CONFIG outConfig, /* i : output audio configuration */ + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : decoder config. structure */ + const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */ + const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, /* i : internal setup handle */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */ + DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: JBM handle */ + Word32 *input_f[], /* i : transport channels */ + Word32 *output[], /* i/o: input/output audio channels */ + const Word16 n_samples_to_render, /* i : output frame length per channel */ + const Word32 output_Fs /* i : output sampling rate */ +) +{ + Word16 i, j; + Word16 sf; + Word16 pos_idx; + ivas_error error; + Word32 gain_lfe; + Word32 tmpLfeBuffer[L_FRAME48k]; + Word16 original_subframes_rendered, original_slots_rendered; + Word32 tmpInputBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word32 *p_tmpInputBuffer[MAX_OUTPUT_CHANNELS]; + Word32 tmpSplitBinBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + + COMBINED_ORIENTATION_DATA combinedOrientationDataLocal; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal; + + /* save current head positions */ + pCombinedOrientationDataLocal = hCombinedOrientationData; + combinedOrientationDataLocal = *pCombinedOrientationDataLocal; + original_subframes_rendered = hTcBuffer->subframes_rendered; + move16(); + original_slots_rendered = hTcBuffer->slots_rendered; + move16(); + + /* copy input */ + FOR( i = 0; i < hIntSetup->nchan_out_woLFE; ++i ) + { + Copy32( input_f[i], tmpInputBuffer[i], n_samples_to_render ); + } + + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) + { + p_tmpInputBuffer[i] = tmpInputBuffer[i]; + move32(); + } + + /* save current head positions */ + pCombinedOrientationDataLocal = hCombinedOrientationData; + combinedOrientationDataLocal = *pCombinedOrientationDataLocal; + move32(); + move32(); + IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + { + FOR( sf = 1; sf < hCombinedOrientationData->num_subframes; ++sf ) + { + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[0], &combinedOrientationDataLocal.Quaternions[sf] ); + FOR( i = 0; i < 3; i++ ) + { + FOR( j = 0; j < 3; j++ ) + { + combinedOrientationDataLocal.Rmat_fx[sf][i][j] = combinedOrientationDataLocal.Rmat_fx[0][i][j]; + move32(); + } + } + } + } + + /* copy LFE to tmpLfeBuffer and apply gain only once */ + IF( GT_16( hIntSetup->num_lfe, 0 ) && NE_16( hIntSetup->index_lfe[0], -1 ) ) + { + Copy32( output[hIntSetup->index_lfe[0]], tmpLfeBuffer, n_samples_to_render ); + gain_lfe = ( ( pCrend != NULL ) && ( pCrend->hHrtfCrend != NULL ) ) ? pCrend->hHrtfCrend->gain_lfe_fx : GAIN_LFE_FX; + v_multc_fixed_16( tmpLfeBuffer, gain_lfe, tmpLfeBuffer, n_samples_to_render ); // q_input_fx - 1 + Scale_sig32( tmpLfeBuffer, n_samples_to_render, 1 ); // q_input_fx + } + ELSE + { + set32_fx( tmpLfeBuffer, 0, n_samples_to_render ); + } + + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; ++pos_idx ) + { + /* Update head positions */ + IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; + + FOR( i = 0; i < hCombinedOrientationData->num_subframes; i++ ) + { + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] ); + Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 + move32(); + modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 ); + Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + + Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + combinedOrientationDataLocal.Quaternions[i] = Quaternions_abs; + move32(); + move32(); + move32(); + move32(); + modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Quaternions_orig[i].q_fact ); + QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + } + modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx, combinedOrientationDataLocal.Rmat_fx, MAX_PARAM_SPATIAL_SUBFRAMES, sub( shl( Quaternions_orig[0].q_fact, 1 ), 32 ), Q30 ); + + pCombinedOrientationDataLocal = &combinedOrientationDataLocal; + move32(); + + hTcBuffer->subframes_rendered = original_subframes_rendered; + hTcBuffer->slots_rendered = original_slots_rendered; + move16(); + move16(); + + /* update combined orientation access index */ + ivas_combined_orientation_set_to_start_index( pCombinedOrientationDataLocal ); + + FOR( i = 0; i < 3; i++ ) + { + Copy32( hCombinedOrientationData->Rmat_prev_fx[pos_idx][i], pCombinedOrientationDataLocal->Rmat_prev_fx[0][i], 3 ); + } + + IF( ( error = ivas_rend_crendProcessSubframe( pCrend, inConfig, outConfig, hDecoderConfig, pCombinedOrientationDataLocal, + hIntSetup, hEFAPdata, hTcBuffer, p_tmpInputBuffer, p_tmpInputBuffer, n_samples_to_render, output_Fs, pos_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + + FOR( i = 0; i < 3; i++ ) + { + Copy32( pCombinedOrientationDataLocal->Rmat_prev_fx[0][i], hCombinedOrientationData->Rmat_prev_fx[pos_idx][i], 3 ); + } + + FOR( i = 0; i < BINAURAL_CHANNELS; ++i ) + { + /* accumulate LFE to output */ + v_add_fx( tmpInputBuffer[i], tmpLfeBuffer, tmpInputBuffer[i], n_samples_to_render ); + + /* move to split bin output buffer */ + Copy32( tmpInputBuffer[i], tmpSplitBinBuffer[add( i_mult( pos_idx, BINAURAL_CHANNELS ), i )], n_samples_to_render ); + } + + /* overwrite rendered channels with input again for next iteration */ + FOR( i = 0; i < hIntSetup->nchan_out_woLFE; ++i ) + { + Copy32( output[i], tmpInputBuffer[i], n_samples_to_render ); + } + + /* restore original headrotation data */ + FOR( i = 0; i < hCombinedOrientationData->num_subframes; i++ ) + { + Copy_Quat_fx( &Quaternions_orig[i], &combinedOrientationDataLocal.Quaternions[i] ); + } + } + + /* copy split binaural rendered signals to final output */ + FOR( i = 0; i < i_mult( BINAURAL_CHANNELS, pMultiBinPoseData->num_poses ); ++i ) + { + Copy32( tmpSplitBinBuffer[i], output[i], n_samples_to_render ); + } + + /* update main combined orientation access index */ + ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_to_render ); + + return IVAS_ERR_OK; +} +#endif diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index d90728d58..8ec066dc9 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -112,11 +112,21 @@ static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBIN static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME] /*q_inp*/[CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 decIm[] /*q_inp*/[CLDFB_NO_CHANNELS_MAX] ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 subframe, Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, Word32 *IIReneLimiter, Word16 q ); + +static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 Rmat[3][3], const Word16 subframe, const Word16 isHeadtracked, const Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, const Word32 *IIReneLimiter, const MASA_ISM_DATA_HANDLE hMasaIsmData ); +#else static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q*/, Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q*/, Word32 Rmat_fx[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const MASA_ISM_DATA_HANDLE hMasaIsmData, Word16 q ); +#endif static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, Word32 Rmat[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat, Word32 outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word8 recompute ); +#else static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat ); +#endif static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ ); @@ -125,7 +135,13 @@ static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 useCachedValue ); static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3] /*Q30*/, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT +static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[] /*Q11*/, const Word16 subframe, const SPLIT_REND_WRAPPER *hSplitRendWrapper, Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ); +#else static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[] /*Q11*/, const Word16 subframe ); +#endif + static void formulate2x2MixingMatrix_fx( Word32 Ein1_fx /*q_Ein*/, Word32 Ein2_fx /*q_Ein*/, Word16 q_Ein, Word32 CinRe_fx /*q_Cin*/, Word32 CinIm_fx /*q_Cin*/, Word16 q_Cin, Word32 Eout1_fx /*q_Eout*/, Word32 Eout2_fx /*q_Eout*/, Word16 q_Eout, Word32 CoutRe_fx /*q_Cout*/, Word32 CoutIm_fx /*q_Cout*/, Word16 q_Cout, Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*Q31*/, Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word16 *q_M, const Word16 regularizationFactor_fx /*Q14*/ ); static void matrixMul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word16 *q_out ); @@ -153,189 +169,226 @@ ivas_error ivas_dirac_dec_init_binaural_data_fx( Word16 tmp_e; Word16 tmp2; ivas_error error; - hDiracDecBin = st_ivas->hDiracDecBin; - IF( hDiracDecBin == NULL ) - { - IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) - { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); - } +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 num_poses, pos_idx; - hDiracDecBin->hTdDecorr = NULL; - hDiracDecBin->hReverb = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; + num_poses = 1; + IF( st_ivas->hSplitBinRend != NULL ) + { + num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; + move16(); } - output_Fs = st_ivas->hDecoderConfig->output_Fs; - move32(); - nBins = st_ivas->hSpatParamRendCom->num_freq_bands; - move16(); - renderer_type = st_ivas->renderer_type; - move32(); - - FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) { - FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) - { - set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins ); - set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins ); - set16_fx( hDiracDecBin->processMtxRePrev_fx[j][k], 0, nBins ); - set16_fx( hDiracDecBin->processMtxImPrev_fx[j][k], 0, nBins ); - } + hDiracDecBin = st_ivas->hDiracDecBin[pos_idx]; + move32(); +#else + hDiracDecBin = st_ivas->hDiracDecBin; +#endif - FOR( k = 0; k < BINAURAL_CHANNELS; k++ ) + IF( hDiracDecBin == NULL ) { - set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins ); - set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins ); - } - set32_fx( hDiracDecBin->ChEnePrev_fx[j], 0, nBins ); - set32_fx( hDiracDecBin->ChEneOutPrev_fx[j], 0, nBins ); - set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins ); - set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins ); - } - set32_fx( hDiracDecBin->ChCrossRePrev_fx, 0, nBins ); - set32_fx( hDiracDecBin->ChCrossImPrev_fx, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins ); - set32_fx( hDiracDecBin->ChCrossReOutPrev_fx, 0, nBins ); - set32_fx( hDiracDecBin->ChCrossImOutPrev_fx, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins ); - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; - move16(); - - hDiracDecBin->q_processMtx = Q15; - hDiracDecBin->q_processMtxSCCR = Q15; - hDiracDecBin->q_processMtxPrev = Q15; - hDiracDecBin->q_processMtxPrevSCCR = Q15; - hDiracDecBin->q_processMtxDec = Q15; - hDiracDecBin->q_processMtxDecPrev = Q15; - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); + IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); + } - FOR( bin = 0; bin < nBins; bin++ ) - { - binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/ - /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ - tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, 2700 << Q15, &tmp_e ); - IF( tmp_e < 0 ) - { - tmp = shl( tmp, tmp_e ); /*q15*/ - tmp_e = 0; - move16(); + hDiracDecBin->hTdDecorr = NULL; + hDiracDecBin->hReverb = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; } - tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q15-tmp_e*/ - tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); /* Q15 */ //*binCenterFreq_fx * EVS_PI / 550.0f*/ - hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ /* Q30 */ - hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); /* Q31 */ - move32(); - move32(); - } - FOR( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ ) - { - hDiracDecBin->diffuseFieldCoherenceX_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceX_fx[bin] ); - hDiracDecBin->diffuseFieldCoherenceY_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceY_fx[bin] ); - hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceZ_fx[bin] ); - move32(); + output_Fs = st_ivas->hDecoderConfig->output_Fs; move32(); + nBins = st_ivas->hSpatParamRendCom->num_freq_bands; + move16(); + renderer_type = st_ivas->renderer_type; move32(); - } - IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */ - { - set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->q_earlyPartEneCorrection = Q28; + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) + { + FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) + { + set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxRePrev_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxImPrev_fx[j][k], 0, nBins ); + } + + FOR( k = 0; k < BINAURAL_CHANNELS; k++ ) + { + set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins ); + } + set32_fx( hDiracDecBin->ChEnePrev_fx[j], 0, nBins ); + set32_fx( hDiracDecBin->ChEneOutPrev_fx[j], 0, nBins ); + set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins ); + set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins ); + } + set32_fx( hDiracDecBin->ChCrossRePrev_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossImPrev_fx, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossReOutPrev_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossImOutPrev_fx, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins ); + hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; move16(); - hDiracDecBin->hReverb = NULL; - } - ELSE IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */ - { - Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins ); - hDiracDecBin->q_earlyPartEneCorrection = Q28; + + hDiracDecBin->q_processMtx = Q15; + hDiracDecBin->q_processMtxSCCR = Q15; + hDiracDecBin->q_processMtxPrev = Q15; + hDiracDecBin->q_processMtxPrevSCCR = Q15; + hDiracDecBin->q_processMtxDec = Q15; + hDiracDecBin->q_processMtxDecPrev = Q15; move16(); - /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ - test(); - test(); - IF( hDiracDecBin->hReverb != NULL && ( ( NE_16( hDiracDecBin->hReverb->numBins, nBins ) ) || - ( NE_16( hDiracDecBin->hReverb->blockSize, CLDFB_SLOTS_PER_SUBFRAME ) ) ) ) + move16(); + move16(); + move16(); + move16(); + move16(); + + FOR( bin = 0; bin < nBins; bin++ ) + { + binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/ + /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ + tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, 2700 << Q15, &tmp_e ); + IF( tmp_e < 0 ) + { + tmp = shl( tmp, tmp_e ); /*q15*/ + tmp_e = 0; + move16(); + } + tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q15-tmp_e*/ + tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); /* Q15 */ //*binCenterFreq_fx * EVS_PI / 550.0f*/ + hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ /* Q30 */ + hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); /* Q31 */ + move32(); + move32(); + } + + FOR( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ ) { - ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) ); + hDiracDecBin->diffuseFieldCoherenceX_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceX_fx[bin] ); + hDiracDecBin->diffuseFieldCoherenceY_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceY_fx[bin] ); + hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceZ_fx[bin] ); + move32(); + move32(); + move32(); } - IF( hDiracDecBin->hReverb == NULL ) + IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */ + { + set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->q_earlyPartEneCorrection = Q28; + move16(); + hDiracDecBin->hReverb = NULL; + } + ELSE IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */ { - /* Todo Philips: Room acoustics should be passed here once the underlying part works. Probably enough to pick it from st_ivas but you know best. */ - IF( NE_32( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, st_ivas->hHrtfParambin ) ), IVAS_ERR_OK ) ) + Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins ); + hDiracDecBin->q_earlyPartEneCorrection = Q28; + move16(); + /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */ + test(); + test(); + IF( hDiracDecBin->hReverb != NULL && ( ( NE_16( hDiracDecBin->hReverb->numBins, nBins ) ) || + ( NE_16( hDiracDecBin->hReverb->blockSize, CLDFB_SLOTS_PER_SUBFRAME ) ) ) ) { - return error; + ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) ); + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( hDiracDecBin->hReverb == NULL && EQ_16( pos_idx, 0 ) ) /* open reverb only for the main direction */ +#else + IF( hDiracDecBin->hReverb == NULL ) +#endif + { + /* Todo Philips: Room acoustics should be passed here once the underlying part works. Probably enough to pick it from st_ivas but you know best. */ + IF( NE_32( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, st_ivas->hHrtfParambin ) ), IVAS_ERR_OK ) ) + { + return error; + } } } - } - ELSE IF( EQ_32( renderer_type, RENDERER_STEREO_PARAMETRIC ) ) - { - set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->q_earlyPartEneCorrection = Q28; - hDiracDecBin->hReverb = NULL; - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; - move16(); - move16(); - } - ELSE /* Not valid renderer type for this renderer */ - { - assert( false ); - } + ELSE IF( EQ_32( renderer_type, RENDERER_STEREO_PARAMETRIC ) ) + { + set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->q_earlyPartEneCorrection = Q28; + hDiracDecBin->hReverb = NULL; + hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; + move16(); + move16(); + } + ELSE /* Not valid renderer type for this renderer */ + { + assert( false ); + } - hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */ + hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */ - if ( hDiracDecBin->hTdDecorr == NULL ) - { - hDiracDecBin->useTdDecorr = 0; - move16(); - } + if ( hDiracDecBin->hTdDecorr == NULL ) + { + hDiracDecBin->useTdDecorr = 0; + move16(); + } - IF( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL ) - { - ivas_dirac_dec_decorr_close_fx( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state ); - } + IF( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL ) + { + ivas_dirac_dec_decorr_close_fx( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state ); + } - IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) ) - { - return error; - } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( pos_idx == 0 ) /* open decorrelator only for the main direction */ + { +#endif + IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) ) + { + return error; + } - test(); - test(); - IF( !hDiracDecBin->useTdDecorr && !( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) ) - { - Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX]; - ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins ); - - IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), - &( hDiracDecBin->h_freq_domain_decorr_ap_state ), - nBins, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - frequency_axis_fx, - BINAURAL_CHANNELS, - output_Fs ) ), - IVAS_ERR_OK ) ) + test(); + test(); + IF( !hDiracDecBin->useTdDecorr && !( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) ) + { + Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX]; + ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins ); + + IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), + &( hDiracDecBin->h_freq_domain_decorr_ap_state ), + nBins, + BINAURAL_CHANNELS, + BINAURAL_CHANNELS, + DIRAC_SYNTHESIS_PSD_LS, + frequency_axis_fx, + BINAURAL_CHANNELS, + output_Fs ) ), + IVAS_ERR_OK ) ) + { + return error; + } + } +#ifdef SPLIT_REND_WITH_HEAD_ROT + } + else { - return error; + hDiracDecBin->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; /* copy the flag, but the implementation re-uses the decorrelated signal */ } - } +#endif - hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); /* Q14 */ - move16(); + hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); /* Q14 */ + move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + st_ivas->hDiracDecBin[pos_idx] = hDiracDecBin; + } +#else st_ivas->hDiracDecBin = hDiracDecBin; +#endif /* allocate transport channels */ IF( st_ivas->hTcBuffer == NULL ) @@ -376,13 +429,37 @@ void ivas_dirac_dec_close_binaural_data( DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle */ ) { - +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; +#endif test(); IF( hBinaural == NULL || *hBinaural == NULL ) { return; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + IF( hBinaural[pos_idx] != NULL ) + { + IF( hBinaural[pos_idx]->hReverb != NULL ) + { + ivas_binaural_reverb_close( &( hBinaural[pos_idx]->hReverb ) ); + } + + ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) ); + + if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL ) + { + ivas_dirac_dec_decorr_close( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) ); + } + + free( hBinaural[pos_idx] ); + hBinaural[pos_idx] = NULL; + } + } +#else IF( ( *hBinaural )->hReverb != NULL ) { ivas_binaural_reverb_close_fx( &( ( *hBinaural )->hReverb ) ); @@ -396,6 +473,7 @@ void ivas_dirac_dec_close_binaural_data( free( *hBinaural ); *hBinaural = NULL; +#endif return; } @@ -603,7 +681,24 @@ static void ivas_dirac_dec_binaural_internal_fx( Word16 nBins, offsetSamples; Word16 i, j; Word16 q_mat, q_out; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; + MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + Word32 tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */ + Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 decorrRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 decorrIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX]; + Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX]; + + hDiracDecBin = st_ivas->hDiracDecBin[0]; +#else hDiracDecBin = st_ivas->hDiracDecBin; +#endif assert( hDiracDecBin ); hSpatParamRendCom = st_ivas->hSpatParamRendCom; nBins = hSpatParamRendCom->num_freq_bands; @@ -904,13 +999,18 @@ static void ivas_dirac_dec_binaural_internal_fx( IF( EQ_16( nchan_transport, 2 ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */ +#endif adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); } } test(); +#ifndef SPLIT_REND_WITH_HEAD_ROT ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, Rmat_fx, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, st_ivas->hMasaIsmData, q_inp ); +#endif IF( EQ_32( config_data.ivas_format, ISM_FORMAT ) ) { @@ -928,6 +1028,13 @@ static void ivas_dirac_dec_binaural_internal_fx( move16(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe, + subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp ); + + ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData ); +#endif nchanSeparateChannels = 0; move16(); @@ -994,91 +1101,991 @@ static void ivas_dirac_dec_binaural_internal_fx( hDiracDecBin->q_processMtxDecPrev = q_mat; move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + pMultiBinPoseData = NULL; + IF( st_ivas->hSplitBinRend != NULL ) + { + pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData; + move32(); + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 ) +#endif + { + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, + tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ ) + { + Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); + Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); + } + } + } + ELSE + { + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL, + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + } +#else ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); +#endif + hDiracDecBin->hDiffuseDist = NULL; + + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 ) + { + /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */ + IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref; + Word32 Rmat_local[3][3]; + + if ( hCombinedOrientationData ) + { + Quaternions_ref = &hCombinedOrientationData->Quaternions[0]; + Copy_Quat_fx( Quaternions_ref, &Quaternions_abs ); + modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, Q22 ); + Quaternions_rot.w_fx = L_negate( 12582912 ); /* signal to use Euler */ + Quat2EulerDegree_fx( Quaternions_abs, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + Quaternions_abs.w_fx = L_negate( 12582912 ); /* signal to use Euler */ + + FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + Quaternions_rot.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_rot.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_rot.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + move32(); + move32(); + move32(); + modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact ); + QuatToRotMat_fx( Quaternions_rot, Rmat_local ); + + hDiracDecBin = st_ivas->hDiracDecBin[pos_idx]; + assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" ); + if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) + { + hDiracDecBin->hDiffuseDist = &diffuseDistData; + } + + /* re-use input covariance for the side renderings */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + Copy32( st_ivas->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands ); + } + Copy32( st_ivas->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands ); + Copy32( st_ivas->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands ); + + ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData ); + + ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + nchanSeparateChannels, st_ivas->hMasaIsmData ); + + + q_mat = hDiracDecBin->q_processMtx; + move16(); + q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev ); + q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec ); + q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) + { + Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat + } + FOR( slot = 0; slot < nchanSeparateChannels; slot++ ) + { + Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + } + } + hDiracDecBin->q_processMtx = q_mat; + move16(); + hDiracDecBin->q_processMtxPrev = q_mat; + move16(); + hDiracDecBin->q_processMtxDec = q_mat; + move16(); + hDiracDecBin->q_processMtxDecPrev = q_mat; + move16(); + + /* re-use reverb and decorr from main direction for the sides */ + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, + tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 0 ); + + /* copy from temporary buffer to the main split rendering buffer */ + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ ) + { + Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); + Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX ); + } + } + + hDiracDecBin->hDiffuseDist = NULL; + } + } + } + + /* update this counter only after the last rendering of split directions */ +#endif + + hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] ); + hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 ); + + move16(); + move16(); + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + scale_sig32( output_fx[ch], imult1616( nBins, hSpatParamRendCom->subframe_nbslots[subframe] ), sub( 11, q_out ) ); // Scaling to Q11 + scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, sub( Q11, st_ivas->cldfbSynDec[ch]->Q_cldfb_state ) ); + st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11; + move16(); + } + + return; +} + + +static void ivas_dirac_dec_decorrelate_slot_fx( + DIRAC_DEC_BIN_HANDLE hDiracDecBin, + const Word16 num_freq_bands, + const Word16 slot, + Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ + Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ + Word16 q_inp, + Word32 decRe[][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ + Word32 decIm[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/ ) +{ + Word16 offset, ch, bin; + Word32 onset_filter_fx[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ + Word32 decorrelatedFrameInterleaved_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ + Word32 protoFrame_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ + Word16 q_decorrelatedFrameInterleaved, q_protoFrame; + const Word16 protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 }; + move16(); + q_protoFrame = q_inp; + move16(); + /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */ + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); + FOR( bin = 0; bin < num_freq_bands; bin++ ) + { + protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )] = inRe[ch][slot][bin]; // q_protoFrame + protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )] = inIm[ch][slot][bin]; // q_protoFrame + move32(); + move32(); + } + } + + /* Decorrelate proto signal to decorrelatedFrameInterleaved */ + ivas_dirac_dec_decorr_process_fx( num_freq_bands, + BINAURAL_CHANNELS, + BINAURAL_CHANNELS, + DIRAC_SYNTHESIS_PSD_LS, + BINAURAL_CHANNELS, + protoFrame_fx, + q_protoFrame, + BINAURAL_CHANNELS, + protoIndexDir, + decorrelatedFrameInterleaved_fx, + &q_decorrelatedFrameInterleaved, + onset_filter_fx, + hDiracDecBin->h_freq_domain_decorr_ap_params, + hDiracDecBin->h_freq_domain_decorr_ap_state ); + + /* De-interleave decorrelated signals*/ + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); + FOR( bin = 0; bin < num_freq_bands; bin++ ) + { + decRe[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )]; // q_inp + decIm[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )]; // q_inp + move32(); + move32(); + } + } + // q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame // + return; +} + + +#ifdef SPLIT_REND_WITH_HEAD_ROT +static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( + DIRAC_DEC_BIN_HANDLE hDiracDecBin, + SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, + PARAMBIN_REND_CONFIG_HANDLE hConfig, + Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/ + Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/ + const Word16 subframe, + Word32 *subFrameTotalEne_fx, + Word16 *subFrameTotalEne_e, + Word32 *IIReneLimiter_fx, + Word16 q ) +{ + Word16 ch, slot, bin; + Word16 nBins, shift; + Word32 IIReneLimiterFactor_fx; // Q26 + Word32 qualityBasedSmFactor_fx; + Word32 lowBitRateEQ_fx[CLDFB_NO_CHANNELS_MAX]; + UWord8 applyLowBitRateEQ; + PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE]; + IVAS_FORMAT ivas_format; + Word32 ivas_total_brate; + Word16 nchan_transport; + Word16 exp, exp1; + Word64 temp64; + Word32 temp; + + ivas_format = hConfig->ivas_format; + move32(); + ivas_total_brate = hConfig->ivas_total_brate; + move32(); + nchan_transport = hConfig->nchan_transport; + move16(); + qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/ + move32(); + qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/ + + nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ + move16(); + + + set32_fx( hDiracDecBin->ChCrossRe_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossIm_fx, 0, nBins ); + + + set16_fx( hDiracDecBin->ChCrossRe_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossIm_e, 0, nBins ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + set32_fx( hDiracDecBin->ChEne_fx[ch], 0, nBins ); + + set16_fx( hDiracDecBin->ChEne_e[ch], 0, nBins ); + } + + set16_fx( subFrameTotalEne_e, 0, CLDFB_NO_CHANNELS_MAX ); + + /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */ + applyLowBitRateEQ = 0; + move16(); + test(); + test(); + IF( ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MC_FORMAT ) ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) + { + applyLowBitRateEQ = 1; + move16(); + IF( EQ_32( ivas_total_brate, IVAS_16k4 ) ) + { + FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) + { + lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = L_add( L_shr( lowBitRateBinauralEQ_fx[bin], 1 ), ONE_IN_Q30 ); // Q31 + move32(); + } + } + ELSE + { + FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ ) + { + lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ_fx[bin]; // Q31 + move32(); + } + } + } + + /* Formulate input and target covariance matrices for this subframe */ + set32_fx( subFrameTotalEne_fx, 0, CLDFB_NO_CHANNELS_MAX ); + + exp = sub( 63, shl( q, 1 ) ); // exp for the energy (inRe_fx * inRe_fx + inIm_fx * inIm_fx) computed below + + /* Calculate input covariance matrix */ + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + { + FOR( bin = 0; bin < nBins; bin++ ) + { + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + Word32 instEne_fx; + temp64 = W_mult0_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ); // 2q + temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // 2q + exp1 = W_norm( temp64 ); + instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2q - 32 + exp1 + /* exp of instEne_fx = 31 - (2q -32 + exp1) = 63 - 2q - exp1 = exp - exp1*/ + + hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], instEne_fx, sub( exp, exp1 ), &hDiracDecBin->ChEne_e[ch][bin] ); + subFrameTotalEne_fx[bin] = BASOP_Util_Add_Mant32Exp( subFrameTotalEne_fx[bin], subFrameTotalEne_e[bin], instEne_fx, sub( exp, exp1 ), &subFrameTotalEne_e[bin] ); + move32(); + move32(); + } + temp64 = W_mult0_32_32( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ); // 2q + temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ); // 2q + exp1 = W_norm( temp64 ); + temp = W_extract_h( W_shl( temp64, exp1 ) ); // // 2q - 32 + exp1 + hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], temp, sub( exp, exp1 ), &hDiracDecBin->ChCrossRe_e[bin] ); + move32(); + + temp64 = W_mult0_32_32( inRe_fx[0][slot][bin], inIm_fx[1][slot][bin] ); // 2q + temp64 = W_sub( temp64, W_mult0_32_32( inIm_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ); // 2q + exp1 = W_norm( temp64 ); + temp = W_extract_h( W_shl( temp64, exp1 ) ); // // 2q - 32 + exp1 + hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], temp, sub( exp, exp1 ), &hDiracDecBin->ChCrossIm_e[bin] ); + move32(); + } + } + + /* Apply EQ at low bit rates */ + IF( applyLowBitRateEQ != 0 ) + { + Word16 lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1; + + FOR( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ ) + { + subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[bin] ); // exp = subFrameTotalEne_e[bin] + move32(); + } + FOR( ; bin < nBins; bin++ ) + { + subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[lastEqBin] ); // exp = subFrameTotalEne_e[bin] + move32(); + } + } + + test(); + test(); + IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, SBA_ISM_FORMAT ) ) && EQ_16( nchan_transport, 2 ) ) + { + Word32 tempRe, tempIm; + Word32 subFrameSumEne_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 subFrameSumEne_e[CLDFB_NO_CHANNELS_MAX]; + + set32_fx( subFrameSumEne_fx, 0, CLDFB_NO_CHANNELS_MAX ); + set16_fx( subFrameSumEne_e, 0, CLDFB_NO_CHANNELS_MAX ); + FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ ) + { + FOR( bin = 0; bin < nBins; bin++ ) + { + tempRe = L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ); // q + tempIm = L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ); // q + temp64 = W_add( W_mult0_32_32( tempRe, tempRe ), W_mult0_32_32( tempIm, tempIm ) ); // 2q + exp1 = W_norm( temp64 ); + temp64 = W_shl( temp64, exp1 ); // 2q + exp1 + subFrameSumEne_fx[bin] = BASOP_Util_Add_Mant32Exp( subFrameSumEne_fx[bin], subFrameTotalEne_e[bin], W_extract_h( temp64 ), sub( exp /* 63 - 2q */, exp1 ) /*31 - (2q + exp1 - 32)*/, &subFrameTotalEne_e[bin] ); + move32(); + } + } + FOR( bin = 0; bin < nBins; bin++ ) + { + temp = L_shl_sat( subFrameTotalEne_fx[bin], sub( subFrameTotalEne_e[bin], subFrameSumEne_e[bin] ) ); // subFrameSumEne_e[bin] + IF( GT_32( subFrameSumEne_fx[bin], temp ) ) + { + subFrameTotalEne_fx[bin] = subFrameSumEne_fx[bin]; + move32(); + subFrameTotalEne_e[bin] = subFrameSumEne_e[bin]; + move16(); + } + } + } + + + test(); + /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */ + IF( EQ_32( ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) + { + IIReneLimiterFactor_fx = L_add( L_shl( 16, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26 + } + ELSE + { + IIReneLimiterFactor_fx = L_add( L_shl( 8, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26 + } + + FOR( bin = 0; bin < nBins; bin++ ) + { + + /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that + * the energy history (IIR) must not be more than double of the current frame energy. This provides more + * robust performance at energy offsets when compared to typical IIR averaging. */ + Word16 num_e, den_e; + Word32 num, den; + num = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_fx[1][bin], hDiracDecBin->ChEne_e[1][bin], &num_e ); + num = Mpy_32_32( num, IIReneLimiterFactor_fx ); /*Q = (31 - num_e + 26 - 31) = (26 - num_e)*/ + den_e = 0; + move16(); + den = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEnePrev_fx[0][bin], hDiracDecBin->ChEnePrev_e[0][bin], hDiracDecBin->ChEnePrev_fx[1][bin], hDiracDecBin->ChEnePrev_e[1][bin], &den_e ); + den = L_max( 1, den ); + IIReneLimiter_fx[bin] = BASOP_Util_Divide3232_Scale_cadence( num, den, &exp ); + exp = add( sub( num_e, den_e ), add( 5, exp ) ); + IF( L_shr_sat( IIReneLimiter_fx[bin], sub( 31, exp ) ) > 0 ) + { + IIReneLimiter_fx[bin] = ONE_IN_Q31; /*Q31*/ + move32(); + } + ELSE + { + IIReneLimiter_fx[bin] = L_shl( IIReneLimiter_fx[bin], exp ); /*Q31*/ + } + + hDiracDecBin->ChCrossRe_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossRe_fx[bin], qualityBasedSmFactor_fx ); + hDiracDecBin->ChCrossIm_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossIm_fx[bin], qualityBasedSmFactor_fx ); + + move32(); + move32(); + move32(); + move32(); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEne_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEne_fx[ch][bin], qualityBasedSmFactor_fx ); + move32(); + } + + hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], Mpy_32_32( hDiracDecBin->ChCrossRePrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossRePrev_e[bin], &hDiracDecBin->ChCrossRe_e[bin] ); + hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossImPrev_e[bin], &hDiracDecBin->ChCrossIm_e[bin] ); + move32(); + move32(); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEnePrev_fx[ch][bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChEnePrev_e[ch][bin], &hDiracDecBin->ChEne_e[ch][bin] ); + move32(); + } + + /* Store energy values and coefficients for next round */ + hDiracDecBin->ChCrossRePrev_fx[bin] = hDiracDecBin->ChCrossRe_fx[bin]; + move32(); + hDiracDecBin->ChCrossImPrev_fx[bin] = hDiracDecBin->ChCrossIm_fx[bin]; + move32(); + hDiracDecBin->ChCrossRePrev_e[bin] = hDiracDecBin->ChCrossRe_e[bin]; + move16(); + hDiracDecBin->ChCrossImPrev_e[bin] = hDiracDecBin->ChCrossIm_e[bin]; + move16(); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin]; + move32(); + hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin]; + move16(); + } + } + + return; +} + +static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( + DIRAC_DEC_BIN_HANDLE hDiracDecBin, + const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, + const PARAMBIN_REND_CONFIG_HANDLE hConfig, + Word32 Rmat_fx[3][3], + const int16_t subframe, + const int16_t isHeadtracked, + Word32 *subFrameTotalEne_fx, + Word16 *subFrameTotalEne_e, + Word32 *IIReneLimiter_fx, + const MASA_ISM_DATA_HANDLE hMasaIsmData ) +{ + Word16 ch, bin; + Word16 separateCenterChannelRendering; + Word16 nBins, idx, shift; + Word32 frameMeanDiffusenessEneWeight_fx[CLDFB_NO_CHANNELS_MAX]; + Word32 qualityBasedSmFactor_fx; + Word16 dirac_read_idx; + PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE]; + IVAS_FORMAT ivas_format; + MC_MODE mc_mode; + Word16 gainCacheBaseIndex; + Word16 q_earlyPartEneCorrection; + Word16 exp, exp1; + Word32 temp; + + separateCenterChannelRendering = hConfig->separateCenterChannelRendering; + move16(); + ivas_format = hConfig->ivas_format; + move32(); + mc_mode = hConfig->mc_mode; + move32(); + qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/ + move32(); + qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/ + + nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */ + move16(); + + q_earlyPartEneCorrection = s_min( Q31, add( getScaleFactor32( hDiracDecBin->earlyPartEneCorrection_fx, nBins ), hDiracDecBin->q_earlyPartEneCorrection ) ); + scale_sig32( hDiracDecBin->earlyPartEneCorrection_fx, nBins, sub( q_earlyPartEneCorrection, hDiracDecBin->q_earlyPartEneCorrection ) ); + hDiracDecBin->q_earlyPartEneCorrection = q_earlyPartEneCorrection; + move16(); + + set32_fx( hDiracDecBin->ChCrossReOut_fx, 0, nBins ); + set32_fx( hDiracDecBin->ChCrossImOut_fx, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossReOut_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossImOut_e, 0, nBins ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + set32_fx( hDiracDecBin->ChEneOut_fx[ch], 0, nBins ); + set16_fx( hDiracDecBin->ChEneOut_e[ch], 0, nBins ); + } + set32_fx( hDiracDecBin->frameMeanDiffuseness_fx, 0, nBins ); + + set32_fx( frameMeanDiffusenessEneWeight_fx, 0, CLDFB_NO_CHANNELS_MAX ); + + FOR( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ ) + { + gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */ + move16(); + } + + /* Determine target covariance matrix containing target binaural properties */ + FOR( bin = 0; bin < nBins; bin++ ) + { + Word32 diffuseness_fx = ONE_IN_Q30; /* ratio1 and ratio2 are subtracted from diffuseness further below */ + Word32 diffusenessValForDecorrelationReduction_fx = ONE_IN_Q30; + Word32 diffEneValForDecorrelationReduction_fx; + Word16 q_diffEneValForDecorrelationReduction; + Word16 surCoh_fx = 0, spreadCoh_fx = 0; /* Default values if spreadSurroundCoherenceApplied == false */ + Word32 diffEne_fx, dirEne_fx, meanEnePerCh_fx; + Word16 q_meanEnePerCh; + Word16 q_diffEne, q_dirEne; + Word16 dirIndex; + move16(); + move16(); + move32(); + move32(); + + /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f. + * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the + * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match + * the early spectrum of the BRIR data, using the spectral correction data in + * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */ + meanEnePerCh_fx = Mpy_32_32( hDiracDecBin->earlyPartEneCorrection_fx[bin], subFrameTotalEne_fx[bin] ); // Q( q_meanEnePerCh ) + q_meanEnePerCh = add( sub( q_earlyPartEneCorrection, subFrameTotalEne_e[bin] ), 1 ); // q_earlyPartEneCorrection + 31 - subFrameTotalEne_e[bin] - 31 + Q1(0.5f) + /* Determine direct part target covariance matrix (for 1 or 2 directions) */ + FOR( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ ) + { + Word16 aziDeg, eleDeg; + Word32 lRealp_fx, lImagp_fx, rRealp_fx, rImagp_fx; + Word32 lRealpTmp_fx, lImagpTmp_fx, rRealpTmp_fx, rImagpTmp_fx; + Word32 hrtfEne_fx[BINAURAL_CHANNELS], hrtfCrossRe_fx, hrtfCrossIm_fx, ratio_fx; + UWord8 isIsmDirection = 0; + move16(); + + test(); + test(); + IF( dirIndex == 0 ) /* For first of the two simultaneous directions */ + { + aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin]; + move16(); + eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin]; + move16(); + ratio_fx = hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin]; + move32(); + spreadCoh_fx = hSpatParamRendCom->spreadCoherence_fx[dirac_read_idx][bin]; + move16(); + gainCacheBaseIndex = 0; + move16(); + } + ELSE IF( NE_32( ivas_format, MASA_ISM_FORMAT ) || ( EQ_32( ivas_format, MASA_ISM_FORMAT ) && LT_16( dirIndex, hSpatParamRendCom->numParametricDirections ) ) ) /* For second of the two simultaneous directions */ + { + IF( LT_32( ( ratio_fx = hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin] ), 10737418 /* 0.01 in Q30 */ ) ) + { + /* This touches only MASA path where second direction always has smaller ratio and + * for non-2dir it is zero. As the whole direction contribution is multiplied with + * the ratio, a very small ratio does not contribute any energy to output. Thus, + * it is better to save complexity. */ + CONTINUE; + } + aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin]; + move16(); + eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin]; + move16(); + spreadCoh_fx = hSpatParamRendCom->spreadCoherence2_fx[dirac_read_idx][bin]; + move16(); + gainCacheBaseIndex = 3; + move16(); + } + ELSE /* For object directions of MASA_ISM_FORMAT */ + { + isIsmDirection = 1; + move16(); + UWord16 ismDirIndex; + ismDirIndex = sub( dirIndex, hSpatParamRendCom->numParametricDirections ); + assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" ); + IF( hMasaIsmData->ism_is_edited[ismDirIndex] ) + { + aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex]; + move16(); + eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex]; + move16(); + } + ELSE + { + aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx]; + move16(); + eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx]; + move16(); + } + ratio_fx = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin]; + move32(); + spreadCoh_fx = 0; + move16(); + gainCacheBaseIndex = add( 6, ismDirIndex ); + } + + diffuseness_fx = L_sub( diffuseness_fx, ratio_fx ); /* diffuseness = 1 - ratio1 - ratio2 */ + + if ( diffuseness_fx < 0 ) + { + diffuseness_fx = 0; + move32(); + } + IF( isIsmDirection ) + { + /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */ + diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, L_shr( ratio_fx, 1 ) ); /*Q30*/ + } + ELSE + { + diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, ratio_fx ); /*Q30*/ + } + + IF( separateCenterChannelRendering ) + { + /* In masa + mono rendering mode, the center directions originate from phantom sources, so the + * spread coherence is increased */ + Word16 azi_scaled, ele_scaled; + Word32 doaVectorX_fx, num, den; + Word16 e = 0, spatialAngleDeg_fx, altSpreadCoh_fx; + move16(); + + azi_scaled = i_mult( aziDeg, 91 ); + ele_scaled = i_mult( eleDeg, 91 ); + doaVectorX_fx = L_mult( getCosWord16R2( azi_scaled ), getCosWord16R2( ele_scaled ) ); /*Q31*/ + num = Sqrt32( L_sub( ONE_IN_Q31, Mpy_32_32( doaVectorX_fx, doaVectorX_fx ) ), &e ); + den = doaVectorX_fx; + move32(); + spatialAngleDeg_fx = BASOP_util_atan2( num, den, e ); // Q13 + Word16 numr, num_e = 0, denr, den_e; + move16(); + num_e = sub( norm_s( spatialAngleDeg_fx ), 1 ); + numr = shl( spatialAngleDeg_fx, num_e ); + denr = 17157; + move16(); + den_e = 4; + move16(); + altSpreadCoh_fx = sub( 32767, shl_sat( div_s( numr, denr ), sub( den_e, num_e ) ) ); // 4289 = pi/6 in Q13 + spreadCoh_fx = s_max( spreadCoh_fx, altSpreadCoh_fx ); + } + + getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex], isHeadtracked ); + + Word16 q_lr = Q28; + move16(); + if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + { + /* Synthesizing spread coherence is not needed for stereo loudspeaker output, + * as directional sound is reproduced with two loudspeakers in any case */ + spreadCoh_fx = 0; + move32(); + } + + IF( spreadCoh_fx > 0 ) + { + Word32 centerMul_fx, sidesMul_fx; + Word32 hrtfEneCenter_fx, hrtfEneSides_fx, hrtfEneRealized_fx; + Word16 eneCorrectionFactor_fx, eneCorrectionFactor_e; + Word16 w1_fx, w2_fx, w3_fx, eq_fx; + + hrtfEneCenter_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), // Q25 + L_add( Mpy_32_32( lImagp_fx, lImagp_fx ), // Q25 + L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), // Q25 + Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q25 + + /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing. + * The following formulas determine the gains for these sources. + * spreadCoh = 0: Only panning + * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi) + * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */ + IF( LT_16( spreadCoh_fx, 16384 ) ) + { + /* 0.0f < spreadCoh < 0.5f */ + sidesMul_fx = L_mult0( spreadCoh_fx, 9459 ); /* 2*sqrt(1/3) in Q13 = 9459 */ // Q28 + centerMul_fx = L_add( L_sub( ONE_IN_Q28, L_shl( spreadCoh_fx, 14 ) ), sidesMul_fx ); // Q28 + } + ELSE + { + /* 0.5f <= spreadCoh < 1.0f */ + // centerMul = 2.0f - ( 2.0f * spreadCoh ); + centerMul_fx = L_shl( sub( 32767, spreadCoh_fx ), 14 ); // Q28 + sidesMul_fx = Isqrt( L_add( L_shr( centerMul_fx, 22 ), L_shl( 2, Q6 ) ) ); // Q28 + centerMul_fx = L_shl( Mpy_32_32( centerMul_fx, sidesMul_fx ), 3 ); // Q28 + } + + /* Apply the gain for the center source of the three coherent sources */ + lRealp_fx = Mpy_32_32( lRealp_fx, centerMul_fx ); // Q25 + lImagp_fx = Mpy_32_32( lImagp_fx, centerMul_fx ); // Q25 + rRealp_fx = Mpy_32_32( rRealp_fx, centerMul_fx ); // Q25 + rImagp_fx = Mpy_32_32( rImagp_fx, centerMul_fx ); // Q25 + + /* Apply the gain for the left source of the three coherent sources */ + getDirectPartGains_fx( bin, add( aziDeg, 30 ), eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 1], isHeadtracked ); + + hrtfEneSides_fx = L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ), // Q25 + L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ), // Q25 + L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ), // Q25 + Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ); // Q25 + lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) ); // Q25 + lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) ); // Q25 + rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) ); // Q25 + rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) ); // Q25 + + /* Apply the gain for the right source of the three coherent sources. + * -30 degrees to 330 wrapping due to internal functions. */ + + getDirectPartGains_fx( bin, aziDeg + 330, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 2], isHeadtracked ); + + hrtfEneSides_fx = L_add( hrtfEneSides_fx, + L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ), // Q25 + L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ), // Q25 + L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ), // Q25 + Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ) ); // Q25 + lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) ); // Q25 + lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) ); // Q25 + rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) ); // Q25 + rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) ); // Q25 + + /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */ + hrtfEneRealized_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), // Q19 + L_add( Mpy_32_32( lImagp_fx, lImagp_fx ), // Q19 + L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), // Q19 + Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q19 + + eneCorrectionFactor_fx = BASOP_Util_Divide3232_Scale( L_add( Mpy_32_32( hrtfEneSides_fx, Mpy_32_32( sidesMul_fx, sidesMul_fx ) ), + Mpy_32_32( hrtfEneCenter_fx, Mpy_32_32( centerMul_fx, centerMul_fx ) ) ), + L_max( 1, hrtfEneRealized_fx ), &eneCorrectionFactor_e ); + + /* Weighting factors to determine appropriate target spectrum for spread coherent sound */ + IF( LT_16( spreadCoh_fx, 16384 ) ) + { + w1_fx = sub( 32767, shl( spreadCoh_fx, 1 ) ); /*Q15*/ + w2_fx = shl( spreadCoh_fx, 1 ); /*Q15*/ + w3_fx = 0; + move16(); + } + ELSE + { + w1_fx = 0; + move16(); + w2_fx = shl( sub( 32767, spreadCoh_fx ), 1 ); /*Q15*/ + w3_fx = shl( sub( spreadCoh_fx, 16384 ), 1 ); /*Q15*/ + } + + test(); + IF( ( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( mc_mode, MC_MODE_MCMASA ) ) ) + { + idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + + /* Apply the target spectrum to the eneCorrectionFactor */ + IF( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */ + { + eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 8192 ), shr( mult_r( add( w2_fx, w3_fx ), spreadCohEne1_fx[idx] ), 1 ) ) ); + eneCorrectionFactor_e = add( eneCorrectionFactor_e, 2 ); + } + ELSE + { + eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 4096 ), add( shr( mult_r( w2_fx, spreadCohEne05_fx[idx] ), 1 ), shr( mult_r( w3_fx, spreadCohEne1_fx[idx] ), 2 ) ) ) ); + eneCorrectionFactor_e = add( eneCorrectionFactor_e, 3 ); + } + } + + /* Equalize the spread coherent combined HRTFs */ + Word16 tmp, tmp_e; + tmp_e = eneCorrectionFactor_e; + move16(); + tmp = Sqrt16( eneCorrectionFactor_fx, &tmp_e ); + IF( GE_16( shr( tmp, sub( 15, tmp_e ) ), 4 ) ) + { + eq_fx = 32767; // Q13 + move16(); + } + ELSE + { + eq_fx = shl( tmp, sub( tmp_e, 2 ) ); // Q13 + } + + lRealp_fx = Mpy_32_16_1( lRealp_fx, eq_fx ); // Q23 + lImagp_fx = Mpy_32_16_1( lImagp_fx, eq_fx ); // Q23 + rRealp_fx = Mpy_32_16_1( rRealp_fx, eq_fx ); // Q23 + rImagp_fx = Mpy_32_16_1( rImagp_fx, eq_fx ); // Q23 + q_lr = Q23; + move16(); + } + + hrtfEne_fx[0] = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), Mpy_32_32( lImagp_fx, lImagp_fx ) ); // Q( 2*q_lr - 31 ) + hrtfEne_fx[1] = L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), Mpy_32_32( rImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 ) + move32(); + move32(); + hrtfCrossRe_fx = L_add( Mpy_32_32( lRealp_fx, rRealp_fx ), Mpy_32_32( lImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 ) + hrtfCrossIm_fx = L_add( Mpy_32_32( -lImagp_fx, rRealp_fx ), Mpy_32_32( lRealp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 ) + + /* Add direct part (1 or 2) covariance matrix */ + dirEne_fx = Mpy_32_32( ratio_fx, meanEnePerCh_fx ); // Q(q_meanEnePerCh - 1) + shift = norm_l( dirEne_fx ); + dirEne_fx = L_shl( dirEne_fx, shift ); + q_dirEne = add( sub( q_meanEnePerCh, 1 ), shift ); + + hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[0] ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Dir ene part*/ + hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[1] ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChEneOut_e[1][bin] ); + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossRe_fx ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChCrossReOut_e[bin] ); /* Dir cross re */ + hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossIm_fx ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChCrossImOut_e[bin] ); /* Dir cross im */ + move32(); + move32(); + move32(); + move32(); + } + + /* Add diffuse / ambient part covariance matrix */ + diffuseness_fx = L_max( 0, diffuseness_fx ); // Q30 + diffEne_fx = Mpy_32_32( diffuseness_fx, meanEnePerCh_fx ); // Q(2q - 32) + shift = norm_l( diffEne_fx ); + diffEne_fx = L_shl( diffEne_fx, shift ); + q_diffEne = add( shift, sub( q_meanEnePerCh, 1 ) ); + + surCoh_fx = hSpatParamRendCom->surroundingCoherence_fx[dirac_read_idx][bin]; // Q15 + move16(); + + diffusenessValForDecorrelationReduction_fx = L_max( 0, diffusenessValForDecorrelationReduction_fx ); // Q30 + diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffusenessValForDecorrelationReduction_fx, meanEnePerCh_fx ); // resulting Q = q_meanEnePerCh - 1 + q_diffEneValForDecorrelationReduction = sub( q_meanEnePerCh, 1 ); + + test(); + IF( ( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( mc_mode, MC_MODE_MCMASA ) ) ) + { + IF( !hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + { + Word32 spectrumModVal; + + idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 ); + /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */ + spectrumModVal = L_add( L_sub( ONE_IN_Q29, L_shl( surCoh_fx, 14 ) ), L_mult( surCoh_fx, surCohEne_fx[idx] ) ); // Q29 + diffEne_fx = Mpy_32_32( diffEne_fx, spectrumModVal ); // Q-2 + q_diffEne = sub( q_diffEne, 2 ); + /* Modify also the value for decorrelation reduction */ + diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffEneValForDecorrelationReduction_fx, spectrumModVal ); // Q-2 + q_diffEneValForDecorrelationReduction = sub( q_diffEneValForDecorrelationReduction, 2 ); + } + } + hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Diff ene part*/ + hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[1][bin] ); - hDiracDecBin->hDiffuseDist = NULL; + move32(); + move32(); + IF( hDiracDecBin->renderStereoOutputInsteadOfBinaural ) + { + /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */ + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_16_1( diffEne_fx, surCoh_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] ); + move32(); + } + ELSE /* When rendering binaural, ambience has frequency dependent ICC. */ + { + test(); + test(); + IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, SBA_ISM_FORMAT ) ) && LT_16( bin, BINAURAL_COHERENCE_DIFFERENCE_BINS ) ) + { + Word32 diffuseFieldCoherence_fx; + Word16 tmp_exp; + temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioX_fx[bin], hDiracDecBin->diffuseFieldCoherenceX_fx[bin] ), 0, Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioY_fx[bin], hDiracDecBin->diffuseFieldCoherenceY_fx[bin] ), 0, &tmp_exp ); + diffuseFieldCoherence_fx = BASOP_Util_Add_Mant32Exp( temp, tmp_exp, Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioZ_fx[bin], hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] ), 0, &tmp_exp ); + temp = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( diffuseFieldCoherence_fx, sub( 32767, surCoh_fx ) ), tmp_exp, L_shl( surCoh_fx, 16 ), 0, &tmp_exp ); + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( temp, diffEne_fx ), add( tmp_exp, sub( 31, q_diffEne ) ), &hDiracDecBin->ChCrossReOut_e[bin] ); + } + ELSE + { + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( L_add( Mpy_32_16_1( hDiracDecBin->diffuseFieldCoherence_fx[bin], sub( 32767, surCoh_fx ) ), L_shl( surCoh_fx, 16 ) ), diffEne_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] ); + } + move32(); + } - hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] ); - hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 ); + /* Store parameters for formulating average diffuseness over frame */ + Word32 frameMeanDiffuseness = BASOP_Util_Add_Mant32Exp( hDiracDecBin->frameMeanDiffuseness_fx[bin], 2 /*Q29*/, diffEneValForDecorrelationReduction_fx, sub( 31, q_diffEneValForDecorrelationReduction ), &exp1 ); // exp = exp1 + frameMeanDiffusenessEneWeight_fx[bin] = L_add( frameMeanDiffusenessEneWeight_fx[bin], meanEnePerCh_fx ); + move32(); - move16(); - move16(); - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - scale_sig32( output_fx[ch], imult1616( nBins, hSpatParamRendCom->subframe_nbslots[subframe] ), sub( 11, q_out ) ); // Scaling to Q11 - scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, sub( Q11, st_ivas->cldfbSynDec[ch]->Q_cldfb_state ) ); - st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11; - move16(); + /* Formulate average diffuseness over frame */ + frameMeanDiffuseness = BASOP_Util_Divide3232_Scale_cadence( frameMeanDiffuseness, L_max( EPSILLON_FX, frameMeanDiffusenessEneWeight_fx[bin] ), &exp ); // exp = exp + 31 - q_meanEnePerCh - exp1 + exp = sub( exp, sub( sub( 31, q_meanEnePerCh ), exp1 ) ); + hDiracDecBin->frameMeanDiffuseness_fx[bin] = L_shl( frameMeanDiffuseness, sub( exp, 2 ) ); // Q29 + move32(); } - return; -} - - -static void ivas_dirac_dec_decorrelate_slot_fx( - DIRAC_DEC_BIN_HANDLE hDiracDecBin, - const Word16 num_freq_bands, - const Word16 slot, - Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ - Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ - Word16 q_inp, - Word32 decRe[][CLDFB_NO_CHANNELS_MAX], /*q_inp*/ - Word32 decIm[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/ ) -{ - Word16 offset, ch, bin; - Word32 onset_filter_fx[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, 60 bins */ - Word32 decorrelatedFrameInterleaved_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ - Word32 protoFrame_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */ - Word16 q_decorrelatedFrameInterleaved, q_protoFrame; - const Word16 protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 }; - move16(); - q_protoFrame = q_inp; - move16(); - /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */ - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + FOR( bin = 0; bin < nBins; bin++ ) { - offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); - FOR( bin = 0; bin < num_freq_bands; bin++ ) + hDiracDecBin->ChCrossReOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossReOut_fx[bin], qualityBasedSmFactor_fx ); + hDiracDecBin->ChCrossImOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossImOut_fx[bin], qualityBasedSmFactor_fx ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )] = inRe[ch][slot][bin]; // q_protoFrame - protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )] = inIm[ch][slot][bin]; // q_protoFrame + hDiracDecBin->ChEneOut_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEneOut_fx[ch][bin], qualityBasedSmFactor_fx ); move32(); + } + hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossReOutPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossReOutPrev_e[bin], &hDiracDecBin->ChCrossReOut_e[bin] ); + hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImOutPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossImOutPrev_e[bin], &hDiracDecBin->ChCrossImOut_e[bin] ); + move32(); + move32(); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + hDiracDecBin->ChEneOut_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[ch][bin], hDiracDecBin->ChEneOut_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEneOutPrev_fx[ch][bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChEneOutPrev_e[ch][bin], &hDiracDecBin->ChEneOut_e[ch][bin] ); move32(); } - } - /* Decorrelate proto signal to decorrelatedFrameInterleaved */ - ivas_dirac_dec_decorr_process_fx( num_freq_bands, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - BINAURAL_CHANNELS, - protoFrame_fx, - q_protoFrame, - BINAURAL_CHANNELS, - protoIndexDir, - decorrelatedFrameInterleaved_fx, - &q_decorrelatedFrameInterleaved, - onset_filter_fx, - hDiracDecBin->h_freq_domain_decorr_ap_params, - hDiracDecBin->h_freq_domain_decorr_ap_state ); - /* De-interleave decorrelated signals*/ - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) - { - offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch ); - FOR( bin = 0; bin < num_freq_bands; bin++ ) + hDiracDecBin->ChCrossReOutPrev_fx[bin] = hDiracDecBin->ChCrossReOut_fx[bin]; + move32(); + hDiracDecBin->ChCrossImOutPrev_fx[bin] = hDiracDecBin->ChCrossImOut_fx[bin]; + move32(); + hDiracDecBin->ChCrossReOutPrev_e[bin] = hDiracDecBin->ChCrossReOut_e[bin]; + move16(); + hDiracDecBin->ChCrossImOutPrev_e[bin] = hDiracDecBin->ChCrossImOut_e[bin]; + move16(); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - decRe[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )]; // q_inp - decIm[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )]; // q_inp + hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin]; move32(); + hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin]; + move16(); + hDiracDecBin->ChEneOutPrev_fx[ch][bin] = hDiracDecBin->ChEneOut_fx[ch][bin]; move32(); + hDiracDecBin->ChEneOutPrev_e[ch][bin] = hDiracDecBin->ChEneOut_e[ch][bin]; + move16(); } } - // q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame // + return; } + +#else static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, @@ -1773,6 +2780,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric return; } +#endif static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, @@ -2381,7 +3389,18 @@ static void ivas_dirac_dec_binaural_process_output_fx( const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, - const Word16 q_mat ) + const Word16 q_mat +#ifdef SPLIT_REND_WITH_HEAD_ROT + , + Word32 outRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 outIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 reverbRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 reverbIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 decorrRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word32 decorrIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + const UWord8 recompute +#endif +) { Word16 slot, bin, chA, chB; Word16 nBins; @@ -2397,8 +3416,10 @@ static void ivas_dirac_dec_binaural_process_output_fx( Word32 decSlotRe_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX]; Word32 outSlotRe_fx[CLDFB_NO_CHANNELS_MAX], outSlotIm_fx[CLDFB_NO_CHANNELS_MAX]; +#ifndef SPLIT_REND_WITH_HEAD_ROT Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; +#endif Word16 q_inp[6][CLDFB_SLOTS_PER_SUBFRAME]; Word16 interpVal_fx; Word32 *decSlotRePointer_fx; @@ -2409,8 +3430,15 @@ static void ivas_dirac_dec_binaural_process_output_fx( IF( processReverb ) { - /* Process second / room effect part of binaural output when needed */ - ivas_binaural_reverb_processSubframe_fx( hDiracDecBin->hReverb, numInChannels, nSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( recompute == 1 ) + { +#endif + /* Process second / room effect part of binaural output when needed */ + ivas_binaural_reverb_processSubframe_fx( hDiracDecBin->hReverb, numInChannels, nSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif } // scaling input and reverb to same q// @@ -2425,7 +3453,11 @@ static void ivas_dirac_dec_binaural_process_output_fx( q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); move16(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) ) +#else IF( ( processReverb ) && LT_16( i, 2 ) ) +#endif { q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) ); q_inp[i][j] = s_min( q_reverb, q_inp[i][j] ); @@ -2453,7 +3485,11 @@ static void ivas_dirac_dec_binaural_process_output_fx( scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ test(); - IF( processReverb && LT_16( i, 2 ) ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) ) +#else + IF( ( processReverb ) && LT_16( i, 2 ) ) +#endif { scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ @@ -2493,7 +3529,27 @@ static void ivas_dirac_dec_binaural_process_output_fx( test(); IF( !hDiracDecBin->useTdDecorr && ( max_band_decorr > 0 ) ) { - ivas_dirac_dec_decorrelate_slot_fx( hDiracDecBin, nBins, slot, inRe_fx, inIm_fx, q_inp_mix, decSlotRe_fx, decSlotIm_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( recompute == 1 ) + { +#endif + ivas_dirac_dec_decorrelate_slot_fx( hDiracDecBin, nBins, slot, inRe_fx, inIm_fx, q_inp_mix, decSlotRe_fx, decSlotIm_fx ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + Copy32( decSlotRe_fx[chA], decorrRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX ); + Copy32( decSlotIm_fx[chA], decorrIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX ); + } + } + else + { + FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) + { + Copy32( decorrRe_fx[chA][slot], decSlotRe_fx[chA], CLDFB_NO_CHANNELS_MAX ); + Copy32( decorrIm_fx[chA][slot], decSlotIm_fx[chA], CLDFB_NO_CHANNELS_MAX ); + } + } +#endif } FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ ) @@ -2583,13 +3639,40 @@ static void ivas_dirac_dec_binaural_process_output_fx( outSlotRePr_fx = &( outSlotRe_fx[0] ); outSlotImPr_fx = &( outSlotIm_fx[0] ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( outRe_fx != NULL && outIm_fx != NULL ) + { + /* provide the data outside in CLDFB domain => mainly for split rendering */ + Copy32( outSlotRePr_fx, outRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX ); + Copy32( outSlotImPr_fx, outIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX ); + Scale_sig32( outRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX, sub( Q6, q_result ) ); // Q6 + Scale_sig32( outIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX, sub( Q6, q_result ) ); // Q6 + } + if ( recompute == 1 ) + { + /* Inverse filter bank */ + cldfbSynthesis_ivas_fx( &outSlotRePr_fx, &outSlotImPr_fx, &( output_fx[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); + cldfbSynDec[chA]->Q_cldfb_state = sub( q_result, 1 ); + move16(); + } +#else cldfbSynthesis_ivas_fx( &outSlotRePr_fx, &outSlotImPr_fx, &( output_fx[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] ); cldfbSynDec[chA]->Q_cldfb_state = sub( q_result, 1 ); move16(); +#endif } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( recompute == 1 ) + { + *q_out = sub( q_result, 1 ); + move16(); + } +#else *q_out = sub( q_result, 1 ); move16(); +#endif + return; } @@ -5394,9 +6477,16 @@ static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[], /* Q11*/ - const Word16 subframe ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 subframe, + const SPLIT_REND_WRAPPER *hSplitRendWrapper, + Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] +#else + const Word16 subframe +#endif +) { - DIRAC_DEC_BIN_HANDLE hDiracDecBin; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; PARAMBIN_REND_CONFIG config_data; @@ -5406,7 +6496,25 @@ static void ivas_masa_ext_rend_parambin_internal_fx( Word16 i, j; Word16 nchan_transport; Word16 q_mat; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + Word32 tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + + /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */ + Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 decorrRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 decorrIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX]; + Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX]; + + hDiracDecBin = hMasaExtRend->hDiracDecBin[0]; +#else hDiracDecBin = hMasaExtRend->hDiracDecBin; +#endif hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; @@ -5526,18 +6634,30 @@ static void ivas_masa_ext_rend_parambin_internal_fx( IF( EQ_16( nchan_transport, 2 ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */ +#endif adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx ); } } test(); +#ifndef SPLIT_REND_WITH_HEAD_ROT ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, Rmat_fx, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, NULL, q_inp ); - +#endif /* Always using CLDFB decorrelation in MASA EXT renderer */ max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe, + subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp ); + ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL ); +#endif + ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_fx, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, 0, NULL ); @@ -5587,11 +6707,139 @@ static void ivas_masa_ext_rend_parambin_internal_fx( move16(); move16(); - ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + pMultiBinPoseData = NULL; + if ( hSplitRendWrapper != NULL ) + { + pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData ); + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im, + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ ) + { + Copy32( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + Copy32( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + } + } + } + else + { + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL, + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + } +#else + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); +#endif hDiracDecBin->hDiffuseDist = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 ) + { + /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */ + IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref; + Word32 Rmat_local[3][3]; + + + if ( hCombinedOrientationData ) + { + Quaternions_ref = &hCombinedOrientationData->Quaternions[0]; + Copy_Quat_fx( Quaternions_ref, &Quaternions_abs ); + modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, Q22 ); + Quaternions_rot.w_fx = L_negate( 12582912 ); /* signal to use Euler */ + Quat2EulerDegree_fx( Quaternions_abs, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + Quaternions_abs.w_fx = L_negate( 12582912 ); /* signal to use Euler */ + + FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + Quaternions_rot.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_rot.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_rot.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + move32(); + move32(); + move32(); + modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact ); + QuatToRotMat_fx( Quaternions_rot, Rmat_local ); + + hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx]; + assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" ); + + /* re-use input covariance for the side renderings */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + mvr2r( hMasaExtRend->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands ); + } + Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands ); + Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands ); + + ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL ); + + ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + 0, NULL ); + + + q_mat = hDiracDecBin->q_processMtx; + move16(); + q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev ); + q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec ); + q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev ); + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ ) + { + Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat + } + } + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + FOR( slot = 0; slot < numInChannels; slot++ ) + { + Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat + } + } + hDiracDecBin->q_processMtx = q_mat; + hDiracDecBin->q_processMtxPrev = q_mat; + hDiracDecBin->q_processMtxDec = q_mat; + hDiracDecBin->q_processMtxDecPrev = q_mat; + move16(); + move16(); + move16(); + move16(); + /* re-use reverb and decorr from main direction for the sides */ + ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im, + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 0 ); + + /* copy from temporary buffer to the main split rendering buffer */ + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ ) + { + Copy32( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + Copy32( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX ); + } + } + + hDiracDecBin->hDiffuseDist = NULL; + } + } + } + + /* update this counter only after the last rendering of split directions */ +#endif + hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] ); hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 ); move16(); @@ -5611,7 +6859,15 @@ void ivas_masa_ext_rend_parambin_render_fx( MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA ext rend structure */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */ Word32 *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output Q11*/ - const Word16 num_subframes ) /* i : number of subframes to render */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 num_subframes, /* i : number of subframes to render */ + const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */ + Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */ + Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* o : rendered orientations for split rend. imag part of cldfb */ +#else + const Word16 num_subframes /* i : number of subframes to render */ +#endif +) { Word16 subframe; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; @@ -5633,8 +6889,11 @@ void ivas_masa_ext_rend_parambin_render_fx( hSpatParamRendCom->slots_rendered = 0; move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_masa_ext_rend_parambin_internal_fx( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag ); +#else ivas_masa_ext_rend_parambin_internal_fx( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx ); - +#endif FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { p_output[ch] += n_samples_sf; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 4a62de19f..269806ccf 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -215,7 +215,15 @@ void ivas_masa_ext_rend_parambin_render_fx( MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA ext rend structure */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */ Word32 *output_f[], /* i/o: synthesized core-coder transport channels/DirAC output Q11*/ - const Word16 num_subframes ); /* i : number of subframes to render */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 num_subframes, /* i : number of subframes to render */ + const SPLIT_REND_WRAPPER *hSplitRendWrapper, /* i : split rendering orientation data */ + Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : rendered orientations for split rend. real part of cldfb */ + Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* o : rendered orientations for split rend. imag part of cldfb */ +#else + const Word16 num_subframes /* i : number of subframes to render */ +#endif +); ivas_error ivas_dirac_dec_init_binaural_data_fx( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i : HRTF structure for rendering */ @@ -1215,11 +1223,21 @@ ivas_error ivas_rend_openCrend( const AUDIO_CONFIG outConfig, RENDER_CONFIG_DATA *hRendCfg, HRTFS_CREND_HANDLE hSetOfHRTF, +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word32 output_Fs, + const Word16 num_poses +#else const Word32 output_Fs +#endif ); void ivas_rend_closeCrend( +#ifdef SPLIT_REND_WITH_HEAD_ROT + CREND_WRAPPER_HANDLE *pCrend , + const Word16 num_poses +#else CREND_WRAPPER_HANDLE *pCrend +#endif ); ivas_error ivas_hrtf_init( @@ -1227,7 +1245,12 @@ ivas_error ivas_hrtf_init( ); ivas_error ivas_rend_initCrendWrapper( +#ifdef SPLIT_REND_WITH_HEAD_ROT + CREND_WRAPPER_HANDLE *pCrend, + const Word16 num_poses +#else CREND_WRAPPER_HANDLE *pCrend +#endif ); ivas_error ivas_rend_crendProcess( const CREND_WRAPPER *pCrend, @@ -1239,7 +1262,12 @@ ivas_error ivas_rend_crendProcess( EFAP_HANDLE hEFAPdata, Word32 *output[], /* i/o: input/output audio channels */ const Word32 output_Fs, +#ifdef SPLIT_REND_WITH_HEAD_ROT + const Word16 num_subframes, /* i : number of subframes to render */ + const Word16 pos_idx /* i : pose index */ +#else const Word16 num_subframes /* i : number of subframes to render */ +#endif ); ivas_error ivas_rend_crendProcessSubframe( const CREND_WRAPPER *pCrend, /* i/o: Crend wrapper handle */ @@ -1254,6 +1282,10 @@ ivas_error ivas_rend_crendProcessSubframe( Word32 *output[], /* i/o: input/output audio channels */ const Word16 n_samples_to_render, /* i : output frame length per channel */ const Word32 output_Fs /* i : output sampling rate */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + , + const Word16 pos_idx +#endif ); @@ -1586,6 +1618,14 @@ void QuatToRotMat( float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +void Quat2EulerDegree( + const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ + float *yaw, /* o : yaw */ + float *pitch, /* o : pitch */ + float *roll /* o : roll */ +); +#endif void rotateAziEle( float azi_in, /* i : output elevation */ @@ -1951,6 +1991,85 @@ void masaPrerendClose_fx( MASA_PREREND_HANDLE *hMasaPrerendPtr /* i/o: prerenderer handle to be closed */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*----------------------------------------------------------------------------------* + * Split rendering + *----------------------------------------------------------------------------------*/ + +ivas_error ivas_td_binaural_renderer_sf_splitBinaural( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *output[], /* i/o: SCE channels / Binaural synthesis */ + const int16_t nSamplesRendered /* i : number of samples to render */ +); + +ivas_error ivas_rend_crendProcessSubframesSplitBin( + const CREND_WRAPPER *pCrend, /* i/o: Crend wrapper handle */ + const AUDIO_CONFIG inConfig, /* i : input audio configuration */ + const AUDIO_CONFIG outConfig, /* i : output audio configuration */ + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const DECODER_CONFIG_HANDLE hDecoderConfig, /* i : decoder config. structure */ + const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, /* i : combined orientation handle */ + const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, /* i : internal setup handle */ + const EFAP_HANDLE hEFAPdata, /* i : EFAP handle */ + DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: JBM handle */ + Word32 *input_f[], /* i : transport channels */ + Word32 *output[], /* i/o: input/output audio channels */ + const Word16 n_samples_to_render, /* i : output frame length per channel */ + const Word32 output_Fs /* i : output sampling rate */ +); + +ivas_error ivas_rend_crendProcessSplitBin( + const CREND_WRAPPER *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const DECODER_CONFIG_HANDLE hDecoderConfig, + const COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, + const IVAS_OUTPUT_SETUP_HANDLE hIntSetup, + EFAP_HANDLE hEFAPdata, + Word32 *output[], + const Word32 output_Fs +); + +ivas_error ivas_rend_openMultiBinCrend( + CREND_WRAPPER_HANDLE *pCrend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word32 output_Fs +); + +void ivas_rend_CldfbMultiBinRendProcess( + const BINAURAL_RENDERER_HANDLE hCldfbRend, + const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + Word32 Cldfb_In_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_In_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Real[MAX_HEAD_ROT_POSES*BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ + Word32 Cldfb_Out_Imag[MAX_HEAD_ROT_POSES*BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 low_res_pre_rend_rot, + const Word16 num_subframes +); + +ivas_error ivas_rend_openCldfb( + HANDLE_CLDFB_FILTER_BANK cldfbAna[MAX_INPUT_CHANNELS], + const AUDIO_CONFIG inConfig, + const Word32 output_Fs +); + +ivas_error ivas_rend_openCldfbRend( + CLDFB_REND_WRAPPER *pCldfbRend, + const AUDIO_CONFIG inConfig, + const AUDIO_CONFIG outConfig, + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, + const Word32 output_Fs +); + +void ivas_rend_closeCldfbRend( + CLDFB_REND_WRAPPER *pCldfbRend +); + +#endif /* clang-format on */ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 14139c534..76e5633fc 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -39,7 +39,7 @@ #include "ivas_stat_com.h" // note: needed for DIRAC_DEC_BIN_HANDLE until #156 is solved #include "stat_com.h" /* Note: Currently needed for CLDFB. */ #include "common_api_types.h" - +#include "isar_stat.h" /*----------------------------------------------------------------------------------* * Output configuration for renderer (e.g. DirAC, MASA, Binaural Renderer...) @@ -769,6 +769,9 @@ typedef struct IVAS_QUATERNION headPositions[MAX_PARAM_SPATIAL_SUBFRAMES]; IVAS_VECTOR3 Pos[MAX_PARAM_SPATIAL_SUBFRAMES]; Word32 crossfade_fx[L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES]; /* Q31 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis; +#endif ivas_orient_trk_state_t *hOrientationTracker; } IVAS_REND_HeadRotData; @@ -790,6 +793,9 @@ typedef struct ivas_binaural_head_track_struct Word16 shd_rot_max_order; ivas_orient_trk_state_t *OrientationTracker; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis; +#endif } HEAD_TRACK_DATA, *HEAD_TRACK_DATA_HANDLE; /*----------------------------------------------------------------------------------* @@ -822,14 +828,22 @@ typedef struct ivas_combined_orientation_struct IVAS_QUATERNION Quaternion_prev_extOrientation; IVAS_QUATERNION Quaternions_ext_interpolation_start; IVAS_QUATERNION Quaternions_ext_interpolation_target; - Word32 Rmat_fx[MAX_PARAM_SPATIAL_SUBFRAMES][3][3]; /* Q30 */ - Word32 Rmat_prev_fx[3][3]; /* Q30 */ + Word32 Rmat_fx[MAX_PARAM_SPATIAL_SUBFRAMES][3][3]; /* Q30 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 Rmat_prev_fx[MAX_HEAD_ROT_POSES][3][3]; +#else + Word32 Rmat_prev_fx[3][3]; +#endif /* Q30 */ Word32 chEneIIR_fx[2][MASA_FREQUENCY_BANDS]; /* independent of the format. MASA bands are suitable for the task and readily available in ROM. */ /* Q(q_chEneIIR) */ Word16 q_chEneIIR; Word32 procChEneIIR_fx[2][MASA_FREQUENCY_BANDS]; /* Q(q_procChEneIIR) */ Word16 q_procChEneIIR; Word16 shd_rot_max_order; IVAS_VECTOR3 listenerPos[MAX_PARAM_SPATIAL_SUBFRAMES]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis; + Word16 sr_low_res_flag; +#endif IVAS_QUATERNION Quaternion_frozen_ext; IVAS_QUATERNION Quaternion_frozen_head; Word8 isExtOrientationFrozen; @@ -1327,7 +1341,11 @@ typedef struct ivas_crend_state_t typedef struct ivas_binaural_crend_wrapper_struct { Word32 binaural_latency_ns; +#ifdef SPLIT_REND_WITH_HEAD_ROT + CREND_HANDLE hCrend[MAX_HEAD_ROT_POSES]; +#else CREND_HANDLE hCrend; +#endif HRTFS_HANDLE hHrtfCrend; Word16 *p_io_qfactor; Word16 io_qfactor; @@ -1342,12 +1360,12 @@ typedef struct ivas_binaural_rendering_struct IVAS_OUTPUT_SETUP_HANDLE hInputSetup; /* pointer to input spatial format for binaural renderer*/ EFAP_HANDLE hEFAPdata; /* EFAP structure*/ Word32 *hoa_dec_mtx; /* pointer to HOA decoder mtx */ /*Q29*/ - int8_t rotInCldfb; /* Flag to enable rotation within bin Renderer in CLDFB*/ - int16_t max_band; /* band upto which rendering is performed */ - int16_t conv_band; /* band upto which convolution in cldfb domain is performed */ - int16_t timeSlots; /* number of time slots of binaural renderer */ - int16_t nInChannels; /* number input channels */ - int8_t render_lfe; /* Flag to render LFE in binaural rendering*/ + Word8 rotInCldfb; /* Flag to enable rotation within bin Renderer in CLDFB*/ + Word16 max_band; /* band upto which rendering is performed */ + Word16 conv_band; /* band upto which convolution in cldfb domain is performed */ + Word16 timeSlots; /* number of time slots of binaural renderer */ + Word16 nInChannels; /* number input channels */ + Word8 render_lfe; /* Flag to render LFE in binaural rendering*/ IVAS_FORMAT ivas_format; /* format; corresponds to st_ivas->ivas_format, unless the signal gets transormed to a different domain for rendering */ /* Convolution module structure */ @@ -1428,6 +1446,21 @@ typedef struct ivas_hrtfs_parambin_struct } HRTFS_PARAMBIN, *HRTFS_PARAMBIN_HANDLE; +#ifdef SPLIT_REND_WITH_HEAD_ROT + +/*----------------------------------------------------------------------------------* + * CLDFB renderer wrapper + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + int32_t binaural_latency_ns; + BINAURAL_RENDERER_HANDLE hCldfbRend; + HRTFS_FASTCONV_HANDLE hHrtfFastConv; + +} CLDFB_REND_WRAPPER; + +#endif /*----------------------------------------------------------------------------------* * Limiter structure @@ -1461,6 +1494,7 @@ typedef struct ivas_LS_setupconversion_struct } LSSETUP_CONVERSION_STRUCT, *LSSETUP_CONVERSION_HANDLE; + typedef struct ivas_LS_setupconversion_matrix_fx { Word16 index; @@ -1520,7 +1554,11 @@ typedef struct ivas_masa_external_rendering_struct RENDERER_TYPE renderer_type; DIRAC_REND_HANDLE hDirACRend; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; +#ifdef SPLIT_REND_WITH_HEAD_ROT + DIRAC_DEC_BIN_HANDLE hDiracDecBin[MAX_HEAD_ROT_POSES]; +#else DIRAC_DEC_BIN_HANDLE hDiracDecBin; +#endif REVERB_STRUCT_HANDLE hReverb; HRTFS_PARAMBIN_HANDLE hHrtfParambin; -- GitLab From a7252203c2b626722f1926c2cb65bb507f1cb180 Mon Sep 17 00:00:00 2001 From: rtyag Date: Fri, 31 Jan 2025 10:56:09 +1100 Subject: [PATCH 05/43] few more updates to split rendering BASOP --- lib_com/cnst.h | 1 + lib_rend/ivas_output_init.c | 21 +- lib_rend/ivas_render_config.c | 27 ++ lib_rend/ivas_rotation.c | 191 +++++++--- lib_rend/ivas_shoebox.c | 1 + lib_rend/lib_rend.c | 684 +++++++++++++++++++++++++++++++--- lib_rend/lib_rend.h | 95 ++++- 7 files changed, 916 insertions(+), 104 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index cb141912c..e86b51472 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -788,6 +788,7 @@ enum #define CLDFB_NO_CHANNELS_MAX 60 /* CLDFB resampling - max number of CLDFB channels, == IVAS_CLDFB_NO_CHANNELS_MAX */ #define CLDFB_NO_CHANNELS_MAX_FX 30720 /*Q9*/ #define CLDFB_NO_COL_MAX 16 /* CLDFB resampling - max number of CLDFB col., == IVAS_CLDFB_NO_COL_MAX */ +#define ONE_BY_CLDFB_NO_COL_MAX_Q31 134217728 #define CLDFB_NO_COL_MAX_SWITCH 6 /* CLDFB resampling - max number of CLDFB col. for switching */ #define CLDFB_NO_COL_MAX_SWITCH_BFI 10 /* CLDFB resampling - max number of CLDFB col. for switching, BFI */ #define CLDFB_OVRLP_MIN_SLOTS 3 /* CLDFB resampling - minimize processing to minimum required for transition frame ACELP->TCX/HQ */ diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 359bea7e6..f20cab785 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -100,6 +100,10 @@ Word16 audioCfg2channels( move16(); BREAK; case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: +#endif case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: nchan_out = 2; @@ -266,6 +270,10 @@ void ivas_output_init( move16(); BREAK; case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: +#endif case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: case IVAS_AUDIO_CONFIG_ISM1: @@ -370,7 +378,12 @@ Word16 ivas_get_nchan_buffers_dec( { nchan_out_buff = s_max( nchan_out_buff, add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ); } - ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || + EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#endif + ) { nchan_out_buff = shl( CPE_CHANNELS, 1 ); } @@ -451,6 +464,12 @@ Word16 ivas_get_nchan_buffers_dec( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + nchan_out_buff = max( nchan_out_buff, st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses * BINAURAL_CHANNELS ); + } +#endif return nchan_out_buff; } diff --git a/lib_rend/ivas_render_config.c b/lib_rend/ivas_render_config.c index d35a6c005..780e1bdd2 100644 --- a/lib_rend/ivas_render_config.c +++ b/lib_rend/ivas_render_config.c @@ -138,5 +138,32 @@ ivas_error ivas_render_config_init_from_rom_fx( move16(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( *hRenderConfig )->split_rend_config.splitRendBitRate = SPLIT_REND_768k; + move32(); + ( *hRenderConfig )->split_rend_config.dof = 3; + move16(); + ( *hRenderConfig )->split_rend_config.hq_mode = 0; + move16(); + ( *hRenderConfig )->split_rend_config.codec_delay_ms = 0; + move16(); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *hRenderConfig )->split_rend_config.isar_frame_size_ms = 20; + move16(); +#endif + ( *hRenderConfig )->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */ + move16(); + ( *hRenderConfig )->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + move32(); + ( *hRenderConfig )->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + move32(); + ( *hRenderConfig )->split_rend_config.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_DEFAULT; + move32(); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ( *hRenderConfig )->split_rend_config.lc3plus_highres = 0; + move16(); +#endif +#endif + return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 8b938a7e0..8651de7f7 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -88,6 +88,9 @@ Word16 square_root30_q12[31] = { static ivas_error combine_external_and_head_orientations( IVAS_QUATERNION *headRotQuaternions, IVAS_VECTOR3 *listenerPos, +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis, /* i : split rend pose prediction axis*/ +#endif EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData ); static void external_target_interpolation_fx( @@ -141,6 +144,10 @@ ivas_error ivas_headTrack_open_fx( move32(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ( *hHeadTrackData )->sr_pose_pred_axis = DEFAULT_AXIS; + move32(); +#endif set32_fx( ( *hHeadTrackData )->chEneIIR_fx[0], 0, MASA_FREQUENCY_BANDS ); set32_fx( ( *hHeadTrackData )->chEneIIR_fx[1], 0, MASA_FREQUENCY_BANDS ); @@ -189,52 +196,66 @@ void QuatToRotMat_fx( Word32 Rmat[3][3] /* o : real-space rotation matrix for this rotation 2*Qx-32 */ ) { - Word32 w = quat.w_fx; // Qx - move32(); - Word32 x = quat.x_fx; - move32(); - Word32 y = quat.y_fx; - move32(); - Word32 z = quat.z_fx; - move32(); - // Adding a guard bit to squared terms since 2*x is not being done in those - // statements (R[0][0], R[1][1], R[2][2]). This is done to avoid L_shl. - Word32 ww = L_shr( Mpy_32_32( w, w ), 1 ); // 2 * Qx - 31 - 1 = 2*Qx-32 - Word32 xx = L_shr( Mpy_32_32( x, x ), 1 ); - Word32 yy = L_shr( Mpy_32_32( y, y ), 1 ); - Word32 zz = L_shr( Mpy_32_32( z, z ), 1 ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( quat.w_fx, L_negate( 12582912 ) ) ) + { + assert( 0 ); + // IVAS_QUATERNION quat_local; + // Euler2Quat_fx( deg2rad( quat.x_fx ), deg2rad( quat.y_fx ), deg2rad( quat.z_fx ), &quat_local ); + // QuatToRotMat_fx( quat_local, Rmat ); + } + else + { +#endif + Word32 w = quat.w_fx; // Qx + move32(); + Word32 x = quat.x_fx; + move32(); + Word32 y = quat.y_fx; + move32(); + Word32 z = quat.z_fx; + move32(); - Word32 wx = Mpy_32_32( w, x ); // 2 * Qx - 31 - Word32 wz = Mpy_32_32( w, z ); - Word32 wy = Mpy_32_32( w, y ); + // Adding a guard bit to squared terms since 2*x is not being done in those + // statements (R[0][0], R[1][1], R[2][2]). This is done to avoid L_shl. + Word32 ww = L_shr( Mpy_32_32( w, w ), 1 ); // 2 * Qx - 31 - 1 = 2*Qx-32 + Word32 xx = L_shr( Mpy_32_32( x, x ), 1 ); + Word32 yy = L_shr( Mpy_32_32( y, y ), 1 ); + Word32 zz = L_shr( Mpy_32_32( z, z ), 1 ); - Word32 xy = Mpy_32_32( x, y ); - Word32 xz = Mpy_32_32( x, z ); + Word32 wx = Mpy_32_32( w, x ); // 2 * Qx - 31 + Word32 wz = Mpy_32_32( w, z ); + Word32 wy = Mpy_32_32( w, y ); - Word32 yz = Mpy_32_32( y, z ); + Word32 xy = Mpy_32_32( x, y ); + Word32 xz = Mpy_32_32( x, z ); - Rmat[0][0] = L_sub( L_sub( L_add( ww, xx ), yy ), zz ); // 2 * Qx - 31 - 1 = 2*Qx-32 - move32(); - Rmat[0][1] = L_sub( xy, wz ); - move32(); - Rmat[0][2] = L_add( xz, wy ); - move32(); + Word32 yz = Mpy_32_32( y, z ); - Rmat[1][0] = L_add( xy, wz ); // 2 * Qx - 32 - move32(); - Rmat[1][1] = L_sub( L_add( L_sub( ww, xx ), yy ), zz ); - move32(); - Rmat[1][2] = L_sub( yz, wx ); - move32(); + Rmat[0][0] = L_sub( L_sub( L_add( ww, xx ), yy ), zz ); // 2 * Qx - 31 - 1 = 2*Qx-32 + move32(); + Rmat[0][1] = L_sub( xy, wz ); + move32(); + Rmat[0][2] = L_add( xz, wy ); + move32(); - Rmat[2][0] = L_sub( xz, wy ); // 2 * Qx - 32 - move32(); - Rmat[2][1] = L_add( yz, wx ); - move32(); - Rmat[2][2] = L_add( L_sub( L_sub( ww, xx ), yy ), zz ); - move32(); + Rmat[1][0] = L_add( xy, wz ); // 2 * Qx - 32 + move32(); + Rmat[1][1] = L_sub( L_add( L_sub( ww, xx ), yy ), zz ); + move32(); + Rmat[1][2] = L_sub( yz, wx ); + move32(); + Rmat[2][0] = L_sub( xz, wy ); // 2 * Qx - 32 + move32(); + Rmat[2][1] = L_add( yz, wx ); + move32(); + Rmat[2][2] = L_add( L_sub( L_sub( ww, xx ), yy ), zz ); + move32(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + } +#endif return; } @@ -711,8 +732,11 @@ void rotateFrame_shd( } /* calculate ambisonics rotation matrices for the previous and current frames */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + SHrotmatgen( SHrotmat_prev, hCombinedOrientationData->Rmat_prev_fx[0], shd_rot_max_order ); +#else SHrotmatgen_fx( SHrotmat_prev, hCombinedOrientationData->Rmat_prev_fx, shd_rot_max_order ); - +#endif SHrotmatgen_fx( SHrotmat /*Q14*/, hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx], shd_rot_max_order ); FOR( i = 0; i < subframe_len; i++ ) @@ -773,7 +797,11 @@ void rotateFrame_shd( { MVR2R_WORD32( hCombinedOrientationData->Rmat_fx[subframe_idx][i], +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCombinedOrientationData->Rmat_prev_fx[0][i], +#else hCombinedOrientationData->Rmat_prev_fx[i], +#endif 3 ); // Q14 } @@ -872,8 +900,11 @@ void rotateFrame_sd( } /* gains for previous subframe rotation */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + rotateAziEle_fx( extract_l( L_shr( hTransSetup.ls_azimuth_fx[ch_in_woLFE], Q22 ) ), extract_l( L_shr( hTransSetup.ls_elevation_fx[ch_in_woLFE], Q22 ) ), &azimuth, &elevation, hCombinedOrientationData->Rmat_prev_fx[0], hTransSetup.is_planar_setup ); +#else rotateAziEle_fx( extract_l( L_shr( hTransSetup.ls_azimuth_fx[ch_in_woLFE], Q22 ) ), extract_l( L_shr( hTransSetup.ls_elevation_fx[ch_in_woLFE], Q22 ) ), &azimuth, &elevation, hCombinedOrientationData->Rmat_prev_fx, hTransSetup.is_planar_setup ); - +#endif test(); test(); IF( hEFAPdata != NULL && ( NE_16( extract_l( L_shr( hTransSetup.ls_azimuth_fx[ch_in_woLFE], Q22 ) ), azimuth ) || NE_16( extract_l( L_shr( hTransSetup.ls_elevation_fx[ch_in_woLFE], Q22 ) ), elevation ) ) ) @@ -967,7 +998,11 @@ void rotateFrame_sd( { MVR2R_WORD32( hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i], // Q30 +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCombinedOrientationData->Rmat_prev_fx[0][i], +#else hCombinedOrientationData->Rmat_prev_fx[i], +#endif 3 ); } /* copy to output */ @@ -1311,6 +1346,9 @@ ivas_error ivas_combined_orientation_open( Word16 j; IVAS_QUATERNION identity; IVAS_VECTOR3 origo; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif identity.w_fx = ONE_IN_Q31; move32(); identity.x_fx = 0; @@ -1380,13 +1418,31 @@ ivas_error ivas_combined_orientation_open( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + FOR( j = 0; j < 3; j++ ) + { + set32_fx( ( *hCombinedOrientationData )->Rmat_prev_fx[pos_idx][j], 0, 3 ); + ( *hCombinedOrientationData )->Rmat_prev_fx[pos_idx][j][j] = ONE_IN_Q30; + move32(); + } + } + ( *hCombinedOrientationData )->sr_pose_pred_axis = DEFAULT_AXIS; + ( *hCombinedOrientationData )->sr_low_res_flag = 0; + move32(); + move16(); +#else FOR( j = 0; j < 3; j++ ) { set32_fx( ( *hCombinedOrientationData )->Rmat_prev_fx[j], 0, 3 ); ( *hCombinedOrientationData )->Rmat_prev_fx[j][j] = ONE_IN_Q30; move32(); } - ( *hCombinedOrientationData )->Quaternion_prev_extOrientation = identity; +#endif + + ( *hCombinedOrientationData ) + ->Quaternion_prev_extOrientation = identity; ( *hCombinedOrientationData )->Quaternion_frozen_ext = identity; ( *hCombinedOrientationData )->Quaternion_frozen_head = identity; set_zero_fx( ( *hCombinedOrientationData )->chEneIIR_fx[0], MASA_FREQUENCY_BANDS ); @@ -1447,6 +1503,9 @@ ivas_error combine_external_and_head_orientations_dec( COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis; +#endif IVAS_QUATERNION *pHeadRotQuaternion = NULL; IVAS_VECTOR3 *listenerPos = NULL; @@ -1454,8 +1513,20 @@ ivas_error combine_external_and_head_orientations_dec( { pHeadRotQuaternion = hHeadTrackData->Quaternions; listenerPos = hHeadTrackData->Pos; +#ifdef SPLIT_REND_WITH_HEAD_ROT + sr_pose_pred_axis = hHeadTrackData->sr_pose_pred_axis; +#endif } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ELSE + { + sr_pose_pred_axis = DEFAULT_AXIS; + } +#endif return combine_external_and_head_orientations( pHeadRotQuaternion, listenerPos, +#ifdef SPLIT_REND_WITH_HEAD_ROT + sr_pose_pred_axis, +#endif hExtOrientationData, hCombinedOrientationData ); } @@ -1472,10 +1543,17 @@ ivas_error combine_external_and_head_orientations_rend( COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */ ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis; +#endif IVAS_QUATERNION *headRotQuaternions = NULL; IVAS_VECTOR3 *listenerPos = NULL; Word16 i; +#ifdef SPLIT_REND_WITH_HEAD_ROT + sr_pose_pred_axis = DEFAULT_AXIS; +#endif + IF( hHeadTrackData != NULL ) { IF( hHeadTrackData->headRotEnabled ) @@ -1483,6 +1561,9 @@ ivas_error combine_external_and_head_orientations_rend( headRotQuaternions = hHeadTrackData->headPositions; listenerPos = hHeadTrackData->Pos; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + sr_pose_pred_axis = hHeadTrackData->sr_pose_pred_axis; +#endif } ELSE IF( hExtOrientationData != NULL ) { @@ -1498,6 +1579,9 @@ ivas_error combine_external_and_head_orientations_rend( } return combine_external_and_head_orientations( headRotQuaternions, listenerPos, +#ifdef SPLIT_REND_WITH_HEAD_ROT + sr_pose_pred_axis, +#endif hExtOrientationData, hCombinedOrientationData ); } @@ -1509,8 +1593,11 @@ ivas_error combine_external_and_head_orientations_rend( * NOTE that the external orientations are inversed. *------------------------------------------------------------------------*/ ivas_error combine_external_and_head_orientations( - IVAS_QUATERNION *headRotQuaternions, /* i : quaternions for head rotation */ - IVAS_VECTOR3 *listenerPos, /* i : listener position */ + IVAS_QUATERNION *headRotQuaternions, /* i : quaternions for head rotation */ + IVAS_VECTOR3 *listenerPos, /* i : listener position */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ISAR_SPLIT_REND_ROT_AXIS sr_pose_pred_axis, /* i : split rend pose prediction axis */ +#endif EXTERNAL_ORIENTATION_HANDLE hExtOrientationData, /* i : external orientation handle */ COMBINED_ORIENTATION_HANDLE hCombinedOrientationData /* i/o: combined orientation handle */ ) @@ -1858,6 +1945,10 @@ ivas_error combine_external_and_head_orientations( hCombinedOrientationData->Quaternions[i].q_fact = add( hCombinedOrientationData->Quaternions[i].q_fact, l_shift ); move16(); } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCombinedOrientationData->sr_pose_pred_axis = sr_pose_pred_axis; +#endif return IVAS_ERR_OK; } @@ -2166,7 +2257,11 @@ static Word32 SHrot_w_fx( IF( m == 0 ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + assert( 0 && "ERROR should not be called\n" ); +#else printf( "ERROR should not be called\n" ); +#endif return 0; } ELSE @@ -2366,7 +2461,11 @@ void ivas_combined_orientation_update_index( Word16 exp, div_result; IF( hCombinedOrientationData != NULL ) { - IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) ) + IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + || hCombinedOrientationData->sr_low_res_flag +#endif + ) { /* only one orientation available anyway or split rendering with low resolution*/ hCombinedOrientationData->subframe_idx = 0; @@ -2423,7 +2522,11 @@ void ivas_combined_orientation_update_start_index( { IF( hCombinedOrientationData != NULL ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) || hCombinedOrientationData->sr_low_res_flag ) +#else IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) ) +#endif { /* only one orientation available anyway or split rendering with low resolution*/ hCombinedOrientationData->subframe_idx = 0; diff --git a/lib_rend/ivas_shoebox.c b/lib_rend/ivas_shoebox.c index 6e27da202..2afaea63e 100644 --- a/lib_rend/ivas_shoebox.c +++ b/lib_rend/ivas_shoebox.c @@ -35,6 +35,7 @@ #include #include "ivas_prot_rend.h" #include "ivas_stat_rend.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "prot.h" #include "prot_fx.h" diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index f230cca25..796b6e0e0 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -36,6 +36,9 @@ #include "ivas_prot.h" #include "ivas_prot_fx.h" #include "ivas_prot_rend.h" +#include "isar_prot.h" +#include "isar_stat.h" +#include "lib_isar_pre_rend.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_rend.h" @@ -57,16 +60,8 @@ /* Maximum buffer length (per channel) in samples. * Keep this separate from L_FRAME48k in case we want to support different size later */ -#define MAX_BUFFER_LENGTH_PER_CHANNEL ( L_FRAME48k ) - -/* Maximum buffer length (total) in samples. */ -/* Maximum buffer length (total) in samples. */ -#define MAX_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) - -#define MAX_BIN_DELAY_SAMPLES 50 /* Maximum supported rendering latency for binaural IRs */ - -/* Frame size required when rendering to binaural */ -#define BINAURAL_RENDERING_FRAME_SIZE_MS 5 +#define MAX_BUFFER_LENGTH ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS ) +#define MAX_BIN_DELAY_SAMPLES 150 /* Maximum supported rendering latency for binaural IRs */ /*-------------------------------------------------------------------* @@ -105,6 +100,11 @@ typedef struct const LSSETUP_CUSTOM_STRUCT *pCustomLsOut; const EFAP_WRAPPER *pEfapOutWrapper; IVAS_REND_HeadRotData *pHeadRotData; // for now removing the const qualifier TODO: will modify later +#ifdef SPLIT_REND_WITH_HEAD_ROT + const RENDER_CONFIG_HANDLE *hhRendererConfig; + const Word16 *pSplitRendBFI; + const SPLIT_REND_WRAPPER *pSplitRendWrapper; +#endif const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData; } rendering_context; /* Common base for input structs */ @@ -130,6 +130,9 @@ typedef struct rotation_matrix_fx rot_mat_prev_fx; pan_vector prev_pan_gains; Word8 firstFrameRendered; +#ifdef SPLIT_REND_WITH_HEAD_ROT + TDREND_WRAPPER splitTdRendWrappers[MAX_HEAD_ROT_POSES - 1]; /* Additional TD Rend instances used for split rendering */ +#endif Word32 *bufferData_fx; Word16 nonDiegeticPan; Word32 nonDiegeticPanGain_fx; /* Q31 */ @@ -162,8 +165,15 @@ typedef struct EFAP_WRAPPER efapInWrapper; TDREND_WRAPPER tdRendWrapper; CREND_WRAPPER_HANDLE crendWrapper; +#ifdef SPLIT_REND_WITH_HEAD_ROT + TDREND_WRAPPER splitTdRendWrappers[MAX_HEAD_ROT_POSES - 1]; /* Additional TD Rend instances used for split rendering */ +#endif REVERB_HANDLE hReverb; +#ifdef SPLIT_REND_WITH_HEAD_ROT + rotation_gains_Word32 rot_gains_prev_fx[MAX_HEAD_ROT_POSES]; +#else rotation_gains_Word32 rot_gains_prev_fx; +#endif Word16 nonDiegeticPan; Word32 nonDiegeticPanGain_fx; lfe_routing lfeRouting; @@ -177,8 +187,15 @@ typedef struct input_base base; // pan_matrix hoaDecMtx; pan_matrix_fx hoaDecMtx_fx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + CLDFB_REND_WRAPPER cldfbRendWrapper; +#endif CREND_WRAPPER_HANDLE crendWrapper; +#ifdef SPLIT_REND_WITH_HEAD_ROT + rotation_gains_fx rot_gains_prev_fx[MAX_HEAD_ROT_POSES]; +#else rotation_gains_fx rot_gains_prev_fx; +#endif Word32 *bufferData_fx; DIRAC_ANA_HANDLE hDirAC; } input_sba; @@ -208,7 +225,14 @@ struct IVAS_REND EFAP_WRAPPER efapOutWrapper; IVAS_LSSETUP_CUSTOM_STRUCT customLsOut; +#ifdef SPLIT_REND_WITH_HEAD_ROT + SPLIT_REND_WRAPPER splitRendWrapper; + IVAS_REND_AudioBuffer splitRendEncBuffer; +#endif IVAS_REND_HeadRotData headRotData; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 splitRendBFI; +#endif EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData; COMBINED_ORIENTATION_HANDLE hCombinedOrientationData; @@ -228,6 +252,21 @@ static void freeMasaExtRenderer( MASA_EXT_REND_HANDLE *hMasaExtRendOut ); static void intermidiate_ext_dirac_render( MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure */ Word16 to_fix ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT +static ivas_error renderSbaToMultiBinauralCldfb( + input_sba *sbaInput, + Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 low_res_pre_rend_rot, + const Word16 num_subframes ); + +static ivas_error renderSbaToMultiBinaural( + input_sba *sbaInput, + const AUDIO_CONFIG outConfig, + Word32 out[][L_FRAME48k] ); +#endif + /*-------------------------------------------------------------------* * Local functions *-------------------------------------------------------------------*/ @@ -306,6 +345,103 @@ static Word32 *getSmplPtr_fx( { return buffer.data_fx + chnlIdx * buffer.config.numSamplesPerChannel + smplIdx; } + +#ifdef SPLIT_REND_WITH_HEAD_ROT +static void convertBitsBufferToInternalBitsBuff( + const IVAS_REND_BitstreamBuffer outBits, + ISAR_SPLIT_REND_BITS_HANDLE hBits ) +{ + hBits->bits_buf = outBits.bits; + hBits->bits_read = outBits.config.bitsRead; + hBits->bits_written = outBits.config.bitsWritten; + hBits->buf_len = outBits.config.bufLenInBytes; + hBits->codec = outBits.config.codec; + hBits->pose_correction = outBits.config.poseCorrection; + hBits->codec_frame_size_ms = outBits.config.codec_frame_size_ms; + + return; +} + +static void convertInternalBitsBuffToBitsBuffer( + IVAS_REND_BitstreamBuffer *hOutBits, + const ISAR_SPLIT_REND_BITS_DATA bits ) +{ + hOutBits->bits = bits.bits_buf; + hOutBits->config.bitsRead = bits.bits_read; + hOutBits->config.bitsWritten = bits.bits_written; + hOutBits->config.bufLenInBytes = bits.buf_len; + hOutBits->config.codec = bits.codec; + hOutBits->config.poseCorrection = bits.pose_correction; + hOutBits->config.codec_frame_size_ms = bits.codec_frame_size_ms; + + return; +} + +static void copyBufferToCLDFBarray( + const IVAS_REND_AudioBuffer buffer, + Word32 re[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 im[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ) +{ + UWord32 smplIdx, slotIdx; + UWord32 numCldfbSamples, num_bands; + UWord32 chnlIdx; + const Word32 *readPtr; + + assert( ( buffer.config.is_cldfb == 1 ) && "for time domain input call copyBufferTo2dArray()" ); + readPtr = buffer.data_fx; + numCldfbSamples = (UWord32) shl( buffer.config.numSamplesPerChannel, 1 ); + num_bands = (UWord32) Mpy_32_32( numCldfbSamples, ONE_BY_CLDFB_NO_COL_MAX_Q31 ); + FOR( chnlIdx = 0; chnlIdx < (UWord32) buffer.config.numChannels; ++chnlIdx ) + { + FOR( slotIdx = 0; slotIdx < CLDFB_NO_COL_MAX; ++slotIdx ) + { + FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx ) + { + re[chnlIdx][slotIdx][smplIdx] = *readPtr++; + } + FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx ) + { + im[chnlIdx][slotIdx][smplIdx] = *readPtr++; + } + } + } + + return; +} + +static void accumulateCLDFBArrayToBuffer( + Word32 re[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 im[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + IVAS_REND_AudioBuffer *buffer ) +{ + UWord32 smplIdx, slotIdx; + UWord32 numCldfbSamples, num_bands; + UWord32 chnlIdx; + Word32 *writePtr; + + assert( ( buffer->config.is_cldfb == 1 ) && "for time domain input call copyBufferTo2dArray()" ); + writePtr = buffer->data_fx; + numCldfbSamples = (UWord32) shl( buffer->config.numSamplesPerChannel, 1 ); + num_bands = (UWord32) Mpy_32_32( numCldfbSamples, ONE_BY_CLDFB_NO_COL_MAX_Q31 ); + FOR( chnlIdx = 0; chnlIdx < (uint32_t) buffer->config.numChannels; ++chnlIdx ) + { + FOR( slotIdx = 0; slotIdx < CLDFB_NO_COL_MAX; ++slotIdx ) + { + FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx ) + { + *writePtr++ += re[chnlIdx][slotIdx][smplIdx]; + } + FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx ) + { + *writePtr++ += im[chnlIdx][slotIdx][smplIdx]; + } + } + } + + return; +} +#endif + static void copyBufferTo2dArray_fx( const IVAS_REND_AudioBuffer buffer, Word32 array[][L_FRAME48k] ) @@ -314,6 +450,10 @@ static void copyBufferTo2dArray_fx( UWord32 chnlIdx; const Word32 *readPtr; +#ifdef SPLIT_REND_WITH_HEAD_ROT + assert( ( buffer.config.is_cldfb == 0 ) && "for CLDFB input call copyBufferToCLDFBarray()" ); +#endif + readPtr = buffer.data_fx; FOR( chnlIdx = 0; chnlIdx < (UWord32) buffer.config.numChannels; ++chnlIdx ) @@ -329,7 +469,7 @@ static void copyBufferTo2dArray_fx( } static void accumulate2dArrayToBuffer_fx( Word32 array[][L_FRAME48k], - IVAS_REND_AudioBuffer *buffer ) + const IVAS_REND_AudioBuffer *buffer ) { Word16 smplIdx, chnlIdx; Word32 *writePtr; @@ -420,6 +560,10 @@ static ivas_error validateOutputAudioConfig( case IVAS_AUDIO_CONFIG_HOA2: case IVAS_AUDIO_CONFIG_HOA3: case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: +#endif case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: case IVAS_AUDIO_CONFIG_MASA1: @@ -496,13 +640,20 @@ IVAS_REND_AudioConfigType getAudioConfigType( static ivas_error validateOutputSampleRate( const Word32 sampleRate, - const AUDIO_CONFIG outConfig ) -{ - IF( NE_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) ) - { + const AUDIO_CONFIG outConfig ){ + + IF( NE_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) ){ /* If no binaural rendering, any sampling rate is supported */ return IVAS_ERR_OK; - } +} +#ifdef SPLIT_REND_WITH_HEAD_ROT +ELSE IF( ( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && NE_32( sampleRate, 48000 ) ) +{ + return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Error: Only 48kHz output sampling rate is supported for split rendering." ); +} +ELSE +{ +#endif /* Otherwise rendering to binaural, support the same set as IVAS decoder */ SWITCH( sampleRate ) @@ -515,6 +666,9 @@ static ivas_error validateOutputSampleRate( } return IVAS_ERR_INVALID_SAMPLING_RATE; +#ifdef SPLIT_REND_WITH_HEAD_ROT +} +#endif } /*-------------------------------------------------------------------* * getAudioConfigNumChannels() @@ -536,6 +690,10 @@ ivas_error getAudioConfigNumChannels( BREAK; case IVAS_AUDIO_CONFIG_STEREO: case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: +#endif case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: case IVAS_AUDIO_CONFIG_MASA2: @@ -1045,6 +1203,10 @@ static ivas_error initHeadRotation_fx( hIvasRend->headRotData.headPositions[i] = quaternionInit_fx(); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + hIvasRend->headRotData.sr_pose_pred_axis = DEFAULT_AXIS; + move32(); +#endif IF( ( hIvasRend->headRotData.hOrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL ) { @@ -1196,6 +1358,11 @@ static rendering_context getRendCtx( ctx.pCustomLsOut = &hIvasRend->customLsOut; ctx.pEfapOutWrapper = &hIvasRend->efapOutWrapper; ctx.pHeadRotData = &hIvasRend->headRotData; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ctx.hhRendererConfig = &hIvasRend->hRendererConfig; + ctx.pSplitRendBFI = &hIvasRend->splitRendBFI; + ctx.pSplitRendWrapper = &hIvasRend->splitRendWrapper; +#endif ctx.pCombinedOrientationData = &hIvasRend->hCombinedOrientationData; return ctx; @@ -1244,8 +1411,11 @@ static ivas_error initIsmMasaRendering( inputIsm->tdRendWrapper.hHrtfTD = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputIsm->crendWrapper, inputIsm->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &inputIsm->crendWrapper ); - +#endif ivas_reverb_close( &inputIsm->hReverb ); IF( NE_32( ( error = ivas_omasa_ana_open( &inputIsm->hOMasa, inSampleRate, inputIsm->total_num_objects ) ), IVAS_ERR_OK ) ) @@ -1267,7 +1437,9 @@ static ivas_error setRendInputActiveIsm( rendering_context rendCtx; AUDIO_CONFIG outConfig; input_ism *inputIsm; - +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 i; +#endif inputIsm = (input_ism *) input; rendCtx = inputIsm->base.ctx; outConfig = *rendCtx.pOutConfig; @@ -1296,57 +1468,97 @@ static ivas_error setRendInputActiveIsm( set_zero_fx( inputIsm->prev_pan_gains_fx, MAX_OUTPUT_CHANNELS ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + inputIsm->splitTdRendWrappers[i] = defaultTdRendWrapper(); + } +#endif + inputIsm->hOMasa = NULL; error = IVAS_ERR_OK; move32(); test(); - IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) ) - { - IF( NE_32( ( error = ivas_rend_openCrend( &inputIsm->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) - { + IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) ){ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_openCrend( &inputIsm->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses ) ), IVAS_ERR_OK ) ){ return error; - } +} +#else + IF( NE_32( ( error = ivas_rend_openCrend( &inputIsm->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ){ + return error; +} +#endif +} +ELSE IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA2 ) ) +{ + IF( NE_32( ( error = initIsmMasaRendering( inputIsm, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) + { + return error; } - ELSE IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA2 ) ) +} +ELSE +{ + Word16 SrcInd[MAX_NUM_TDREND_CHANNELS]; + Word16 num_src; + Word16 ivas_format; + IF( EQ_32( getAudioConfigType( inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ) { - IF( NE_32( ( error = initIsmMasaRendering( inputIsm, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) - { - return error; - } + ivas_format = MC_FORMAT; } ELSE { - Word16 SrcInd[MAX_NUM_TDREND_CHANNELS]; - Word16 num_src; - Word16 ivas_format; - IF( EQ_32( getAudioConfigType( inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ) - { - ivas_format = MC_FORMAT; - } - ELSE + ivas_format = ISM_FORMAT; + } + + move16(); + IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) ) + { + return error; + } + + + Word16 nchan_rend = num_src; + move16(); + + test(); + IF( EQ_16( ivas_format, MC_FORMAT ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ) + { + nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */ + } + FOR( Word16 nS = 0; nS < nchan_rend; nS++ ) + { + TDREND_SRC_t *Src_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[SrcInd[nS]]; + IF( Src_p != NULL ) { - ivas_format = ISM_FORMAT; + IF( Src_p->SrcSpatial_p != NULL ) + { + Src_p->SrcSpatial_p->q_Pos_p = Q31; + move16(); + } + TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[nS]->SrcSpatial_p; + SrcSpatial_p->q_Pos_p = Q31; + move16(); } + } - move16(); - IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* Open TD renderer wrappers */ + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + if ( ( error = ivas_td_binaural_open_ext_fx( &inputIsm->splitTdRendWrappers[i], inConfig, hRendCfg, NULL, *inputIsm->base.ctx.pOutSampleRate, SrcInd, &num_src ) ) != IVAS_ERR_OK ) { return error; } - Word16 nchan_rend = num_src; - move16(); + /* Assert same delay as main TD renderer */ + assert( inputIsm->splitTdRendWrappers[i].binaural_latency_ns == inputIsm->tdRendWrapper.binaural_latency_ns ); - test(); - IF( EQ_16( ivas_format, MC_FORMAT ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ) - { - nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */ - } FOR( Word16 nS = 0; nS < nchan_rend; nS++ ) { - TDREND_SRC_t *Src_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[SrcInd[nS]]; + TDREND_SRC_t *Src_p = inputIsm->splitTdRendWrappers[i].hBinRendererTd->Sources[SrcInd[nS]]; IF( Src_p != NULL ) { IF( Src_p->SrcSpatial_p != NULL ) @@ -1354,28 +1566,34 @@ static ivas_error setRendInputActiveIsm( Src_p->SrcSpatial_p->q_Pos_p = Q31; move16(); } - TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[nS]->SrcSpatial_p; + TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputIsm->splitTdRendWrappers[i].hBinRendererTd->Sources[nS]->SrcSpatial_p; SrcSpatial_p->q_Pos_p = Q31; move16(); } } + } - IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) +#endif + + IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + { + IF( NE_32( ( error = ivas_reverb_open_fx( &( inputIsm->hReverb ), outConfig, NULL, inputIsm->tdRendWrapper.hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, hRendCfg, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) { - IF( NE_32( ( error = ivas_reverb_open_fx( &( inputIsm->hReverb ), outConfig, NULL, inputIsm->tdRendWrapper.hBinRendererTd->HrFiltSet_p->lr_energy_and_iac_fx, hRendCfg, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) - { - return error; - } + return error; } } +} - return IVAS_ERR_OK; +return IVAS_ERR_OK; } static void clearInputIsm( input_ism *inputIsm ) { rendering_context rendCtx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t i; +#endif rendCtx = inputIsm->base.ctx; @@ -1384,7 +1602,11 @@ static void clearInputIsm( initRendInputBase_fx( &inputIsm->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); /* Free input's internal handles */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputIsm->crendWrapper, inputIsm->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &inputIsm->crendWrapper ); +#endif ivas_reverb_close( &inputIsm->hReverb ); @@ -1394,6 +1616,13 @@ static void clearInputIsm( inputIsm->tdRendWrapper.hHrtfTD = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + ivas_td_binaural_close( &inputIsm->splitTdRendWrappers[i].hBinRendererTd ); + inputIsm->splitTdRendWrappers[i].hHrtfTD = NULL; + } +#endif ivas_omasa_ana_close( &( inputIsm->hOMasa ) ); @@ -2123,6 +2352,10 @@ static ivas_error updateMcPanGains( SWITCH( outConfig ) { case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: +#endif BREAK; /* Do nothing */ case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: @@ -2172,6 +2405,9 @@ static ivas_error initMcBinauralRendering( Word32 binauralDelayNs; Word32 outSampleRate; Word8 useTDRend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t i; +#endif /* Allocate TD binaural renderer for custom loudspeaker layouts (regardless of headrotation) or planar MC layouts with headrotation, CREND for the rest */ @@ -2203,11 +2439,28 @@ static ivas_error initMcBinauralRendering( inputMc->tdRendWrapper.hHrtfTD = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( !reconfigureFlag || !useTDRend ) + { + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + IF( inputMc->splitTdRendWrappers[i].hBinRendererTd != NULL ) + { + ivas_td_binaural_close_fx( &inputMc->splitTdRendWrappers[i].hBinRendererTd ); + inputMc->splitTdRendWrappers[i].hHrtfTD = NULL; + } + } + } +#endif /* if we need to use TD renderer and CREND was open, close it */ IF( useTDRend ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputMc->crendWrapper, inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &inputMc->crendWrapper ); +#endif } test(); @@ -2266,6 +2519,44 @@ static ivas_error initMcBinauralRendering( } } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + /* Open TD renderer wrappers */ + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + IF( ( error = ivas_td_binaural_open_ext_fx( &inputMc->splitTdRendWrappers[i], inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate, SrcInd, &num_src ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Assert same delay as main TD renderer */ + assert( inputMc->splitTdRendWrappers[i].binaural_latency_ns == inputMc->tdRendWrapper.binaural_latency_ns ); + + FOR( Word16 nS = 0; nS < nchan_rend; nS++ ) + { + TDREND_SRC_t *Src_p = inputMc->splitTdRendWrappers[i].hBinRendererTd->Sources[SrcInd[nS]]; + IF( Src_p != NULL ) + { + IF( Src_p->SrcSpatial_p != NULL ) + { + Src_p->SrcSpatial_p->q_Pos_p = 31; + move16(); + } + IF( inputMc->splitTdRendWrappers[i].hBinRendererTd->Sources[nS] != NULL ) + { + TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputMc->splitTdRendWrappers[i].hBinRendererTd->Sources[nS]->SrcSpatial_p; + SrcSpatial_p->q_Pos_p = 31; + move16(); + } + } + } + } + } + +#endif + test(); IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && inputMc->hReverb == NULL ) { @@ -2278,7 +2569,11 @@ static ivas_error initMcBinauralRendering( ELSE IF( !useTDRend && inputMc->crendWrapper == NULL ) { /* open CREND */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_openCrend( &inputMc->crendWrapper, ( EQ_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ) ? IVAS_AUDIO_CONFIG_7_1_4 : inConfig, outConfig, hRendCfg, NULL, outSampleRate, ( ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) ? inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses : 1 ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_openCrend( &inputMc->crendWrapper, ( EQ_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ) ? IVAS_AUDIO_CONFIG_7_1_4 : inConfig, outConfig, hRendCfg, NULL, outSampleRate ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -2337,7 +2632,11 @@ static ivas_error initMcMasaRendering( inputMc->tdRendWrapper.hHrtfTD = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputMc->crendWrapper, inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &inputMc->crendWrapper ); +#endif ivas_reverb_close( &inputMc->hReverb ); @@ -2423,10 +2722,16 @@ static ivas_error setRendInputActiveMc( const IVAS_REND_InputId id, RENDER_CONFIG_DATA *hRendCfg ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 i; +#endif ivas_error error; rendering_context rendCtx; AUDIO_CONFIG outConfig; input_mc *inputMc; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 pos_idx; +#endif inputMc = (input_mc *) input; rendCtx = inputMc->base.ctx; @@ -2455,7 +2760,14 @@ static ivas_error setRendInputActiveMc( inputMc->hReverb = NULL; inputMc->hMcMasa = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + initRotGainsWord32_fx( inputMc->rot_gains_prev_fx[pos_idx] ); + } +#else initRotGainsWord32_fx( inputMc->rot_gains_prev_fx ); +#endif inputMc->lfeRouting = defaultLfeRouting( inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ); set32_fx( inputMc->lfeDelayBuffer_fx, 0, MAX_BIN_DELAY_SAMPLES ); inputMc->binauralDelaySmp = 0; @@ -2463,7 +2775,16 @@ static ivas_error setRendInputActiveMc( test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + inputMc->splitTdRendWrappers[i] = defaultTdRendWrapper(); + } + + IF( EQ_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) ) +#else IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) +#endif { IF( NE_32( ( error = initMcBinauralRendering( inputMc, inConfig, outConfig, hRendCfg, FALSE ) ), IVAS_ERR_OK ) ) { @@ -2491,6 +2812,9 @@ static void clearInputMc( input_mc *inputMc ) { rendering_context rendCtx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 i; +#endif rendCtx = inputMc->base.ctx; freeMcLfeDelayBuffer_fx( &inputMc->lfeDelayBuffer_fx ); @@ -2503,7 +2827,11 @@ static void clearInputMc( efap_free_data_fx( &inputMc->efapInWrapper.hEfap ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputMc->crendWrapper, inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &inputMc->crendWrapper ); +#endif ivas_reverb_close( &inputMc->hReverb ); @@ -2513,6 +2841,16 @@ static void clearInputMc( inputMc->tdRendWrapper.hHrtfTD = NULL; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) + { + IF( inputMc->splitTdRendWrappers[i].hBinRendererTd != NULL ) + { + ivas_td_binaural_close( &inputMc->splitTdRendWrappers[i].hBinRendererTd ); + inputMc->splitTdRendWrappers[i].hHrtfTD = NULL; + } + } +#endif ivas_mcmasa_ana_close( &( inputMc->hMcMasa ) ); @@ -2634,12 +2972,58 @@ static ivas_error updateSbaPanGains( case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: SWITCH( outConfig ) { - case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: { - IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) + IF( EQ_32( hRendCfg->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) ) { - return error; + assert( inConfig == IVAS_AUDIO_CONFIG_HOA3 && ( *rendCtx.pOutSampleRate == 48000 ) && "split binaural fast conv mode is currently supported with HOA3 input and 48k sampling rate only" ); + if ( ( error = ivas_rend_openCldfbRend( &inputSba->cldfbRendWrapper, inConfig, outConfig, &rendCtx.pSplitRendWrapper->multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + assert( ( *rendCtx.pOutSampleRate == 48000 ) && "split binaural crend mode is currently supported with 48k sampling rate only" ); + if ( ( error = ivas_rend_openMultiBinCrend( &inputSba->crendWrapper, inConfig, outConfig, + &rendCtx.pSplitRendWrapper->multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + break; + } +#endif + case IVAS_AUDIO_CONFIG_BINAURAL: + { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( hRendCfg->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + { + if ( ( error = ivas_rend_openCldfbRend( &inputSba->cldfbRendWrapper, inConfig, outConfig, + &rendCtx.pSplitRendWrapper->multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else +#endif + { +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses ) ), IVAS_ERR_OK ) ) + + { + return error; + } +#else + IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) + + { + return error; + } +#endif } } BREAK; @@ -2649,11 +3033,17 @@ static ivas_error updateSbaPanGains( { return error; } - +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses ) ), IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) ) { return error; } +#endif BREAK; default: return IVAS_ERR_INVALID_OUTPUT_FORMAT; @@ -2682,7 +3072,11 @@ static ivas_error initSbaMasaRendering( { ivas_error error; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputSba->crendWrapper, inputSba->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses ); +#else ivas_rend_closeCrend( &inputSba->crendWrapper ); +#endif IF( NE_32( ( error = ivas_dirac_ana_open_fx( &inputSba->hDirAC, inSampleRate ) ), IVAS_ERR_OK ) ) { @@ -2702,6 +3096,9 @@ static ivas_error setRendInputActiveSba( rendering_context rendCtx; AUDIO_CONFIG outConfig; input_sba *inputSba; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; +#endif inputSba = (input_sba *) input; rendCtx = inputSba->base.ctx; @@ -2713,17 +3110,36 @@ static ivas_error setRendInputActiveSba( return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = allocateInputBaseBufferData_fx( &inputSba->bufferData_fx, MAX_CLDFB_BUFFER_LENGTH ) ), IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_32( ( error = allocateInputBaseBufferData_fx( &inputSba->bufferData_fx, MAX_BUFFER_LENGTH ) ), IVAS_ERR_OK ) ) { return error; } +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT + initRendInputBase_fx( &inputSba->base, inConfig, id, rendCtx, inputSba->bufferData_fx, MAX_CLDFB_BUFFER_LENGTH ); +#else initRendInputBase_fx( &inputSba->base, inConfig, id, rendCtx, inputSba->bufferData_fx, MAX_BUFFER_LENGTH ); +#endif setZeroPanMatrix_fx( inputSba->hoaDecMtx_fx ); inputSba->crendWrapper = NULL; inputSba->hDirAC = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) + { + initRotGains_fx( inputSba->rot_gains_prev_fx[pos_idx] ); + } +#else initRotGains_fx( inputSba->rot_gains_prev_fx ); +#endif test(); IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_MASA2 ) ) @@ -2752,8 +3168,17 @@ static void clearInputSba( initRendInputBase_fx( &inputSba->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_rend_closeCrend( &inputSba->crendWrapper, rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses ); + + IF( inputSba->cldfbRendWrapper.hCldfbRend != NULL ) + { + ivas_rend_closeCldfbRend( &inputSba->cldfbRendWrapper ); + } +#else /* Free input's internal handles */ ivas_rend_closeCrend( &inputSba->crendWrapper ); +#endif ivas_dirac_ana_close_fx( &( inputSba->hDirAC ) ); @@ -2860,6 +3285,9 @@ ivas_error IVAS_REND_Open( const Word16 num_subframes ) { Word16 i; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 j; +#endif IVAS_REND_HANDLE hIvasRend; ivas_error error; Word16 numOutChannels; @@ -2929,6 +3357,10 @@ ivas_error IVAS_REND_Open( } /* Initialize inputs */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + isar_init_split_rend_handles( &hIvasRend->splitRendWrapper ); + hIvasRend->splitRendEncBuffer.data_fx = NULL; +#endif FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) { @@ -2936,6 +3368,13 @@ ivas_error IVAS_REND_Open( hIvasRend->inputsIsm[i].crendWrapper = NULL; hIvasRend->inputsIsm[i].hReverb = NULL; hIvasRend->inputsIsm[i].tdRendWrapper.hBinRendererTd = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( j = 0; j < MAX_HEAD_ROT_POSES - 1; ++j ) + { + hIvasRend->inputsIsm[i].splitTdRendWrappers[j].hBinRendererTd = NULL; + hIvasRend->inputsIsm[i].splitTdRendWrappers[j].hHrtfTD = NULL; + } +#endif hIvasRend->inputsIsm[i].nonDiegeticPan = nonDiegeticPan; move16(); hIvasRend->inputsIsm[i].nonDiegeticPanGain_fx = nonDiegeticPanGain; @@ -2959,6 +3398,13 @@ ivas_error IVAS_REND_Open( hIvasRend->inputsMc[i].nonDiegeticPanGain_fx = nonDiegeticPanGain; move32(); hIvasRend->inputsMc[i].hMcMasa = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + FOR( j = 0; j < MAX_HEAD_ROT_POSES - 1; ++j ) + { + hIvasRend->inputsMc[i].splitTdRendWrappers[j].hBinRendererTd = NULL; + hIvasRend->inputsMc[i].splitTdRendWrappers[j].hHrtfTD = NULL; + } +#endif } FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) @@ -2966,6 +3412,10 @@ ivas_error IVAS_REND_Open( initRendInputBase_fx( &hIvasRend->inputsSba[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 ); hIvasRend->inputsSba[i].crendWrapper = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend = NULL; + hIvasRend->inputsSba[i].cldfbRendWrapper.hHrtfFastConv = NULL; +#endif hIvasRend->inputsSba[i].bufferData_fx = NULL; hIvasRend->inputsSba[i].hDirAC = NULL; } @@ -3361,6 +3811,124 @@ static ivas_error findFreeInputSlot_fx( } +#ifdef SPLIT_REND_WITH_HEAD_ROT +static Word16 getCldfbRendFlag( + IVAS_REND_HANDLE hIvasRend, /* i : Renderer handle */ + const IVAS_REND_AudioConfigType new_configType ) +{ + Word16 i; + Word16 numMasaInputs = 0, numSbaInputs = 0, numIsmInputs = 0, numMcInputs = 0; + Word16 isCldfbRend; + + move16(); + move16(); + move16(); + move16(); + + isCldfbRend = 0; + move16(); + + IF( hIvasRend->hRendererConfig != NULL ) + { + FOR( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) + { + numMasaInputs = add( numMasaInputs, ( hIvasRend->inputsMasa[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) ? 0 : 1 ); + move16(); + } + FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i ) + { + numSbaInputs = add( numSbaInputs, ( hIvasRend->inputsSba[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ? 0 : 1 ); + move16(); + } + FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + numIsmInputs = add( numIsmInputs, ( hIvasRend->inputsIsm[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) ? 0 : 1 ); + move16(); + } + FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) + { + numMcInputs = add( numMcInputs, ( hIvasRend->inputsMc[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ? 0 : 1 ); + move16(); + } + + IF( GT_16( numIsmInputs, 0 ) || GT_16( numMcInputs, 0 ) ) + { + isCldfbRend = 0; + move16(); + } + ELSE IF( GT_16( numMasaInputs, 0 ) || ( GT_16( numSbaInputs, 0 ) && EQ_32( hIvasRend->hRendererConfig->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) ) ) + { + isCldfbRend = 1; + move16(); + } + } + + return isCldfbRend; +} + +/*------------------------------------------------------------------------- + * Function ivas_pre_rend_init() + * + * + *------------------------------------------------------------------------*/ + +static ivas_error ivas_pre_rend_init( + SPLIT_REND_WRAPPER *pSplitRendWrapper, + IVAS_REND_AudioBuffer *pSplitRendEncBuffer, + ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, + IVAS_REND_HeadRotData headRotData, + const Word32 outputSampleRate, + const AUDIO_CONFIG outConfig, + const Word16 cldfb_in_flag, + const Word16 num_subframes ) +{ + ivas_error error; + IVAS_REND_AudioBufferConfig bufConfig; + + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + ISAR_PRE_REND_GetMultiBinPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData, headRotData.sr_pose_pred_axis ); + } + else if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) + { + isar_renderSplitUpdateNoCorrectionPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData ); + } + + if ( ( error = ISAR_PRE_REND_open( pSplitRendWrapper, pSplit_rend_config, outputSampleRate, cldfb_in_flag, outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, num_subframes, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*allocate for CLDFB in and change to TD during process if needed*/ + bufConfig.numSamplesPerChannel = MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL; + bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; + bufConfig.is_cldfb = 1; + pSplitRendEncBuffer->config = bufConfig; + + if ( ( pSplitRendEncBuffer->data_fx = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + } + else + { + IVAS_REND_AudioBufferConfig bufConfig2; + + bufConfig2.numSamplesPerChannel = 0; + bufConfig2.numChannels = 0; + bufConfig2.is_cldfb = 0; + pSplitRendEncBuffer->config = bufConfig2; + pSplitRendEncBuffer->data_fx = NULL; + } + + return IVAS_ERR_OK; +} + +#endif + + /*-------------------------------------------------------------------* * IVAS_REND_AddInput() * diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 5af21427f..60d217bad 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -34,6 +34,7 @@ #define LIB_REND_H #include "common_api_types.h" +#include "ivas_stat_rend.h" #include "basop_util.h" #include @@ -55,6 +56,26 @@ typedef float IVAS_REND_LfePanMtx[RENDERER_MAX_INPUT_LFE_CHANNELS][IVAS_MAX_OUTPUT_CHANNELS]; typedef Word32 IVAS_REND_LfePanMtx_fx[RENDERER_MAX_INPUT_LFE_CHANNELS][IVAS_MAX_OUTPUT_CHANNELS]; +#ifdef SPLIT_REND_WITH_HEAD_ROT +typedef struct +{ + Word32 bufLenInBytes; + Word32 bitsWritten; + Word32 bitsRead; + ISAR_SPLIT_REND_CODEC codec; + ISAR_SPLIT_REND_POSE_CORRECTION_MODE poseCorrection; + Word16 codec_frame_size_ms; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 isar_frame_size_ms; + Word16 lc3plus_highres; +#endif +} IVAS_REND_BitstreamBufferConfig; +typedef struct +{ + IVAS_REND_BitstreamBufferConfig config; + UWord8 *bits; +} IVAS_REND_BitstreamBuffer; +#endif typedef struct { @@ -212,11 +233,45 @@ Word16 IVAS_REND_FeedRenderConfig( const IVAS_RENDER_CONFIG_DATA renderConfig /* i : Render configuration struct */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +ivas_error IVAS_REND_FeedSplitBinauralBitstream( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + IVAS_REND_BitstreamBuffer *hBits /* i : buffer for input bitstream */ +); + +ivas_error IVAS_REND_GetSplitBinauralSamples( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio, /* i/o: buffer for output audio */ + bool* needNewFrame +); + +ivas_error IVAS_REND_GetSplitBinauralBitstream( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio, /* i/o: buffer for output audio */ + IVAS_REND_BitstreamBuffer *hBits /* o : buffer for output bitstream */ +); + +ivas_error IVAS_REND_GetSplitRendBitstreamHeader( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */ + ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */ + Word16 *pCodec_frame_size_ms /* o: pointer to codec frame size setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + Word16 *pIsar_frame_size_ms /* o: pointer to isar frame size setting */ +#endif +); +#endif + ivas_error IVAS_REND_SetHeadRotation( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_QUATERNION headRot, /* i : head orientations for next rendering call */ const IVAS_VECTOR3 Pos, /* i : listener positions for next rendering call */ - const Word16 sf_idx /* i : subframe index */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const ISAR_SPLIT_REND_ROT_AXIS rot_axis, /* i : external control for rotation axis for split rendering*/ +#endif + const Word16 sf_idx /* i : subframe index */ ); /* Head rotation becomes enabled by calling IVAS_REND_SetHeadRotation. Use this to disable. */ @@ -250,6 +305,11 @@ ivas_error IVAS_REND_SetReferenceVector( const IVAS_VECTOR3 refPos /* i : Reference position */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +ivas_error IVAS_REND_SetSplitRendBFI( + IVAS_REND_HANDLE hIvasRend, + const Word16 bfi); +#endif ivas_error IVAS_REND_SetExternalOrientation( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ @@ -309,6 +369,39 @@ void IVAS_REND_Close( IVAS_REND_HANDLE* phIvasRend /* i/o: Pointer to renderer handle */ ); +#ifdef SPLIT_REND_WITH_HEAD_ROT +/* Split binaural rendering functions */ + +ivas_error IVAS_REND_openCldfb( + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS], + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_OUTPUT_CHANNELS], + const Word16 num_in_chs, + const Word16 num_out_chs, + const Word32 output_Fs +); + +void IVAS_REND_closeCldfb( + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS], + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_OUTPUT_CHANNELS] +); + +void IVAS_REND_cldfbAnalysis_ts_wrapper( + const Word32 *timeIn, /* i : time buffer */ + Word32 realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ + Word32 imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ + const Word16 samplesToProcess, /* i : samples to process */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filterbank state */ +); + +void IVAS_REND_cldfbSynthesis_wrapper( + Word32 **realBuffer, /* i : real values */ + Word32 **imagBuffer, /* i : imag values */ + Word32 *timeOut, /* o : output time domain samples */ + const Word16 samplesToProcess, /* i : number of processed samples */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filter bank state */ +); +#endif + #ifdef FIX_DISCLAIMER /* Disclaimer and info printing */ -- GitLab From e4e3f76f6e08e4341f3a4aaa9f3f75d38646ebe2 Mon Sep 17 00:00:00 2001 From: rtyag Date: Fri, 31 Jan 2025 21:56:12 +1100 Subject: [PATCH 06/43] temp changes in lib rend --- Workspace_msvc/Workspace_msvc.sln | 12 + lib_rend/lib_rend.c | 1708 +++++++++++++++++++++++++---- 2 files changed, 1491 insertions(+), 229 deletions(-) diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln index 5449368aa..ac2e76b52 100644 --- a/Workspace_msvc/Workspace_msvc.sln +++ b/Workspace_msvc/Workspace_msvc.sln @@ -99,6 +99,18 @@ Global {95030B82-70CD-4C6B-84D4-61096035BEA2}.Release|Win32.ActiveCfg = Release|Win32 {95030B82-70CD-4C6B-84D4-61096035BEA2}.Release|Win32.Build.0 = Release|Win32 {95030B82-70CD-4C6B-84D4-61096035BEA2}.Release|x64.ActiveCfg = Release|Win32 + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619}.Debug|Win32.ActiveCfg = Debug|Win32 + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619}.Debug|Win32.Build.0 = Debug|Win32 + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619}.Debug|x64.ActiveCfg = Debug|Win32 + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619}.Release|Win32.ActiveCfg = Release|Win32 + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619}.Release|Win32.Build.0 = Release|Win32 + {869A305E-D99E-4C3A-BDB3-AA57ABCCE619}.Release|x64.ActiveCfg = Release|Win32 + {12374ADC-0E5C-4FDD-B903-71D572413831}.Debug|Win32.ActiveCfg = Debug|Win32 + {12374ADC-0E5C-4FDD-B903-71D572413831}.Debug|Win32.Build.0 = Debug|Win32 + {12374ADC-0E5C-4FDD-B903-71D572413831}.Debug|x64.ActiveCfg = Debug|Win32 + {12374ADC-0E5C-4FDD-B903-71D572413831}.Release|Win32.ActiveCfg = Release|Win32 + {12374ADC-0E5C-4FDD-B903-71D572413831}.Release|Win32.Build.0 = Release|Win32 + {12374ADC-0E5C-4FDD-B903-71D572413831}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 796b6e0e0..c5156c2a5 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3885,34 +3885,38 @@ static ivas_error ivas_pre_rend_init( ivas_error error; IVAS_REND_AudioBufferConfig bufConfig; - if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + IF( EQ_32( pSplit_rend_config->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) { ISAR_PRE_REND_GetMultiBinPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData, headRotData.sr_pose_pred_axis ); } - else if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) + ELSE IF( EQ_32( pSplit_rend_config->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) ) { isar_renderSplitUpdateNoCorrectionPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData ); } - if ( ( error = ISAR_PRE_REND_open( pSplitRendWrapper, pSplit_rend_config, outputSampleRate, cldfb_in_flag, outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, num_subframes, 0 ) ) != IVAS_ERR_OK ) + IF( ( error = ISAR_PRE_REND_open( pSplitRendWrapper, pSplit_rend_config, outputSampleRate, cldfb_in_flag, outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, num_subframes, 0 ) ) != IVAS_ERR_OK ) { return error; } /*allocate for CLDFB in and change to TD during process if needed*/ bufConfig.numSamplesPerChannel = MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL; - bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; + bufConfig.numChannels = i_mult( BINAURAL_CHANNELS, pSplitRendWrapper->multiBinPoseData.num_poses ); bufConfig.is_cldfb = 1; pSplitRendEncBuffer->config = bufConfig; + move16(); + move16(); + move16(); + move32(); - if ( ( pSplitRendEncBuffer->data_fx = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) + IF( ( pSplitRendEncBuffer->data_fx = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) { return IVAS_ERR_FAILED_ALLOC; } } - else + ELSE { IVAS_REND_AudioBufferConfig bufConfig2; @@ -3921,6 +3925,11 @@ static ivas_error ivas_pre_rend_init( bufConfig2.is_cldfb = 0; pSplitRendEncBuffer->config = bufConfig2; pSplitRendEncBuffer->data_fx = NULL; + move16(); + move16(); + move16(); + move32(); + move32(); } return IVAS_ERR_OK; @@ -3954,6 +3963,19 @@ ivas_error IVAS_REND_AddInput_fx( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && hIvasRend->splitRendEncBuffer.data_fx == NULL && hIvasRend->hRendererConfig != NULL ) + { + Word16 cldfb_in_flag; + cldfb_in_flag = getCldfbRendFlag( hIvasRend, getAudioConfigType( inConfig ) ); + + IF( ( error = ivas_pre_rend_init( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif + SWITCH( getAudioConfigType( inConfig ) ) { @@ -4062,7 +4084,11 @@ ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout( test(); test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) ) +#else IF( EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) +#endif { IF( NE_32( ( error = initMcBinauralRendering( inputMc, inputMc->base.inConfig, hIvasRend->outputConfig, hIvasRend->hRendererConfig, FALSE ) ), IVAS_ERR_OK ) ) { @@ -4404,6 +4430,27 @@ ivas_error IVAS_REND_GetDelay_fx( { IF( NE_32( hIvasRend->inputsSba[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( hIvasRend->splitRendWrapper.hBinHrSplitPreRend != NULL ) + { + if ( hIvasRend->hRendererConfig->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + { + latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; + } + else + { + latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; + } + max_latency_ns = max( max_latency_ns, latency_ns ); + } + else if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) + { + latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; + latency_ns += IVAS_FB_DEC_DELAY_NS; + max_latency_ns = max( max_latency_ns, latency_ns ); + } + else +#endif { IF( hIvasRend->inputsSba[i].crendWrapper != NULL ) { @@ -4454,6 +4501,9 @@ ivas_error IVAS_REND_FeedInputAudio_fx( ivas_error error; input_base *inputBase; Word16 numInputChannels; +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 cldfb2tdSampleFact; +#endif /* Validate function arguments */ test(); @@ -4463,7 +4513,14 @@ ivas_error IVAS_REND_FeedInputAudio_fx( } test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + cldfb2tdSampleFact = ( inputAudio.config.is_cldfb ) ? 2 : 1; + + if ( inputAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 0 ) || + ( ( MAX_BUFFER_LENGTH_PER_CHANNEL * cldfb2tdSampleFact ) < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 1 ) ) +#else IF( inputAudio.config.numSamplesPerChannel <= 0 || LT_16( MAX_BUFFER_LENGTH_PER_CHANNEL, inputAudio.config.numSamplesPerChannel ) ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Buffer size outside of supported range" ); } @@ -4476,8 +4533,15 @@ ivas_error IVAS_REND_FeedInputAudio_fx( test(); move32(); // move added for typecasting +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && + ( inputAudio.config.numSamplesPerChannel * 1000 / cldfb2tdSampleFact ) != ( BINAURAL_RENDERING_FRAME_SIZE_MS * hIvasRend->num_subframes ) * hIvasRend->sampleRateOut ) +#else IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && NE_32( L_mult0( inputAudio.config.numSamplesPerChannel, 1000 ), (Word32) W_mult0_32_32( L_mult0( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" ); } @@ -4508,7 +4572,11 @@ ivas_error IVAS_REND_FeedInputAudio_fx( MVR2R_WORD32( inputAudio.data_fx, inputBase->inputBuffer.data_fx, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel / cldfb2tdSampleFact; +#else inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel; +#endif move32(); return IVAS_ERR_OK; @@ -4704,6 +4772,23 @@ Word16 IVAS_REND_GetRenderConfig( Copy32( hRCin->roomAcoustics.pAcoustic_rt60_fx, hRCout->roomAcoustics.pAcoustic_rt60_fx, CLDFB_NO_CHANNELS_MAX ); Copy32( hRCin->roomAcoustics.pAcoustic_dsr_fx, hRCout->roomAcoustics.pAcoustic_dsr_fx, CLDFB_NO_CHANNELS_MAX ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + hRCout->split_rend_config.splitRendBitRate = SPLIT_REND_768k; + hRCout->split_rend_config.dof = 3; + hRCout->split_rend_config.hq_mode = 0; + hRCout->split_rend_config.codec_delay_ms = 0; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hRCout->split_rend_config.isar_frame_size_ms = 20; +#endif + hRCout->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */ + hRCout->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + hRCout->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hRCout->split_rend_config.lc3plus_highres = 0; +#endif +#endif + hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er; hRCout->roomAcoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity; @@ -4726,6 +4811,9 @@ Word16 IVAS_REND_FeedRenderConfig( ) { RENDER_CONFIG_HANDLE hRenderConfig; +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_error error; +#endif test(); IF( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL ) @@ -4761,6 +4849,35 @@ Word16 IVAS_REND_FeedRenderConfig( Copy32( renderConfig.roomAcoustics.AbsCoeff_fx, hRenderConfig->roomAcoustics.AbsCoeff_fx, IVAS_ROOM_ABS_COEFF ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + hRenderConfig->split_rend_config = renderConfig.split_rend_config; + /* Overwrite any pose correction settings if 0 DOF (no pose correction) was selected */ + if ( hRenderConfig->split_rend_config.dof == 0 ) + { + hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + } + + hRenderConfig->split_rend_config.codec = renderConfig.split_rend_config.codec; + + if ( ( error = isar_split_rend_validate_config( &hRenderConfig->split_rend_config, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Must re-initialize split rendering config in case renderer config is updated after adding renderer inputs */ + /* if its not initialized yet then no need to re-initialize, initialization will happen while adding inputs*/ + if ( hIvasRend->splitRendEncBuffer.data_fx != NULL && hIvasRend->hRendererConfig != NULL ) + { + int16_t cldfb_in_flag; + cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); + ISAR_PRE_REND_close( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer ); + + if ( ( error = ivas_pre_rend_init( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + { + return error; + } + } +#endif return IVAS_ERR_OK; } @@ -4774,7 +4891,10 @@ ivas_error IVAS_REND_SetHeadRotation( IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ const IVAS_QUATERNION headRot, /* i : head orientations for next rendering call */ const IVAS_VECTOR3 Pos, /* i : listener positions for next rendering call */ - const Word16 sf_idx /* i : subframe index */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + const ISAR_SPLIT_REND_ROT_AXIS rot_axis, /* i : external control for rotation axis for split rendering */ +#endif + const Word16 sf_idx /* i : subframe index */ ) { Word16 i; @@ -4859,6 +4979,10 @@ ivas_error IVAS_REND_SetHeadRotation( return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + hIvasRend->headRotData.sr_pose_pred_axis = rot_axis; +#endif + hIvasRend->headRotData.Pos[sf_idx] = Pos; return IVAS_ERR_OK; @@ -4904,6 +5028,25 @@ ivas_error IVAS_REND_DisableHeadRotation( return IVAS_ERR_OK; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-------------------------------------------------------------------* + * IVAS_REND_SetSplitRendBFI() + * + * + *-------------------------------------------------------------------*/ + +ivas_error +IVAS_REND_SetSplitRendBFI( + IVAS_REND_HANDLE hIvasRend, + const int16_t bfi ) +{ + hIvasRend->splitRendBFI = bfi; + + return IVAS_ERR_OK; +} +#endif + + /*-------------------------------------------------------------------* * IVAS_REND_SetOrientationTrackingMode() * @@ -5581,9 +5724,20 @@ static Word16 getNumSubframesInBuffer( const IVAS_REND_AudioBuffer *buffer, const Word32 sampleRate ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t cldfb2tdShift; + + cldfb2tdShift = buffer->config.is_cldfb ? 1 : 0; + + Word16 scale, temp = extract_l( Mpy_32_32( sampleRate, 10737418 /* 1 / FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES in Q31 */ ) ); + temp = BASOP_Util_Divide1616_Scale( buffer->config.numSamplesPerChannel, temp, &scale ); + temp = shr( temp, sub( 15, scale ) ); /* Q0 */ + temp = shr( temp, cldfb2tdShift ); +#else Word16 scale, temp = extract_l( Mpy_32_32( sampleRate, 10737418 /* 1 / FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES in Q31 */ ) ); temp = BASOP_Util_Divide1616_Scale( buffer->config.numSamplesPerChannel, temp, &scale ); temp = shr( temp, sub( 15, scale ) ); /* Q0 */ +#endif return temp; } @@ -5776,12 +5930,19 @@ static ivas_error renderIsmToBinauralRoom( move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* render 7_1_4 with BRIRs */ + IF( NE_32( ( error = ivas_rend_crendProcess( ismInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, + NULL, NULL, NULL, NULL, p_tmpRendBuffer, *ismInput->base.ctx.pOutSampleRate, + getNumSubframesInBuffer( &outAudio, *ismInput->base.ctx.pOutSampleRate ), 0 ) ), + IVAS_ERR_OK ) ) +#else /* render 7_1_4 with BRIRs */ IF( NE_32( ( error = ivas_rend_crendProcess( ismInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, NULL, NULL, NULL, NULL, p_tmpRendBuffer, *ismInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *ismInput->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) ) - +#endif { return error; } @@ -6069,6 +6230,109 @@ static ivas_error renderIsmToSba( return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +static ivas_error renderIsmToSplitBinaural( + input_ism *ismInput, + const IVAS_REND_AudioBuffer outAudio ) +{ + ivas_error error; + float tmpProcessing[MAX_NUM_OBJECTS][L_FRAME48k]; + int16_t pos_idx; + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + const SPLIT_REND_WRAPPER *pSplitRendWrapper; + IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; + int16_t i; + float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + int16_t output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; + int16_t ism_md_subframe_update_ext; + + push_wmops( "renderIsmToSplitBinaural" ); + + pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper; + pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; + + /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */ + ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms_fx / ( 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + + pCombinedOrientationData = *ismInput->base.ctx.pCombinedOrientationData; + + if ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + for ( i = 1; i < pCombinedOrientationData->num_subframes; ++i ) + { + pCombinedOrientationData->Quaternions[i] = pCombinedOrientationData->Quaternions[0]; + } + } + + /* Save current head positions */ + for ( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) + { + originalHeadRot[i] = pCombinedOrientationData->Quaternions[i]; + } + + /* Copy input audio to a processing buffer. */ + copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing ); + + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + /* Update head positions */ + if ( pos_idx != 0 ) + { + for ( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) + { + if ( originalHeadRot[i].w == -3.0f ) + { + pCombinedOrientationData->Quaternions[i].w = -3.0f; + pCombinedOrientationData->Quaternions[i].x = originalHeadRot[i].x + pMultiBinPoseData->relative_head_poses[pos_idx][0]; + pCombinedOrientationData->Quaternions[i].y = originalHeadRot[i].y + pMultiBinPoseData->relative_head_poses[pos_idx][1]; + pCombinedOrientationData->Quaternions[i].z = originalHeadRot[i].z + pMultiBinPoseData->relative_head_poses[pos_idx][2]; + } + else + { + pCombinedOrientationData->Quaternions[i].w = -3.0f; + Quat2EulerDegree( originalHeadRot[i], + &pCombinedOrientationData->Quaternions[i].z, + &pCombinedOrientationData->Quaternions[i].y, + &pCombinedOrientationData->Quaternions[i].x ); + pCombinedOrientationData->Quaternions[i].x += pMultiBinPoseData->relative_head_poses[pos_idx][0]; + pCombinedOrientationData->Quaternions[i].y += pMultiBinPoseData->relative_head_poses[pos_idx][1]; + pCombinedOrientationData->Quaternions[i].z += pMultiBinPoseData->relative_head_poses[pos_idx][2]; + } + } + } + + /* Render */ + if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[pos_idx - 1], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, + NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Copy rendered audio to tmp storage buffer. Copying directly to output would + * overwrite original audio, which is still needed for rendering next head pose. */ + mvr2r( tmpProcessing[0], tmpBinaural[2 * pos_idx], output_frame ); + mvr2r( tmpProcessing[1], tmpBinaural[2 * pos_idx + 1], output_frame ); + + /* Overwrite processing buffer with original input audio again */ + copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing ); + } + + /* Restore original head rotation */ + for ( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) + { + pCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; + } + + accumulate2dArrayToBuffer( tmpBinaural, &outAudio ); + pop_wmops(); + + /* Encoding to split rendering bitstream done at a higher level */ + return IVAS_ERR_OK; +} +#endif + + static void renderIsmToMasa( input_ism *ismInput, IVAS_REND_AudioBuffer outAudio, @@ -6180,6 +6444,12 @@ static ivas_error renderInputIsm( case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: error = renderIsmToBinauralRoom( ismInput, outAudio, &exp ); BREAK; +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + error = renderIsmToSplitBinaural( ismInput, outAudio ); + break; +#endif case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: error = renderIsmToBinauralReverb( ismInput, outAudio ); BREAK; @@ -6249,11 +6519,17 @@ static ivas_error renderActiveInputsIsm( } static ivas_error renderLfeToBinaural_fx( const input_mc *mcInput, +#ifdef SPLIT_REND_WITH_HEAD_ROT + const AUDIO_CONFIG outConfig, +#endif IVAS_REND_AudioBuffer outAudio, Word16 in_q, Word16 out_q ) { Word16 lfe_idx; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pose_idx, num_poses; +#endif Word32 gain_fx; Word16 ear_idx, i, r_shift; Word32 tmpLfeBuffer[MAX_BUFFER_LENGTH_PER_CHANNEL]; @@ -6261,7 +6537,11 @@ static ivas_error renderLfeToBinaural_fx( const Word32 *lfeInput; Word32 *writePtr; +#ifdef SPLIT_REND_WITH_HEAD_ROT + assert( ( getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && "Must be binaural output" ); +#else assert( ( outAudio.config.numChannels == 2 ) && "Must be binaural output" ); +#endif push_wmops( "renderLfeToBinaural" ); gain_fx = GAIN_LFE_WORD32; /* 1.88364911f in Q30 */ @@ -6312,6 +6592,27 @@ static ivas_error renderLfeToBinaural_fx( move32(); } } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* Copy LFE to left and right binaural channels for all poses */ + if ( mcInput->base.ctx.pSplitRendWrapper != NULL ) + { + num_poses = mcInput->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses; + } + else + { + num_poses = 1; + } + + for ( pose_idx = 0; pose_idx < num_poses; ++pose_idx ) + { + for ( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx ) + { + writePtr = getSmplPtr_fx( outAudio, pose_idx * BINAURAL_CHANNELS + ear_idx, 0 ); + v_add_fixed( writePtr, tmpLfeBuffer, writePtr, frame_size, 0 ); /* Q(out_q) */ + } + } +#else /* SPLIT_REND_WITH_HEAD_ROT */ /* Copy LFE to left and right ears */ FOR( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx ) { @@ -6319,6 +6620,7 @@ static ivas_error renderLfeToBinaural_fx( move32(); v_add_fixed( writePtr, tmpLfeBuffer, writePtr, frame_size, 0 ); /* Q(out_q) */ } +#endif pop_wmops(); @@ -6395,7 +6697,11 @@ static ivas_error renderMcToBinaural( tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); set32_fx( tmpRotBuffer.data_fx, 0, imult1616( tmpRotBuffer.config.numSamplesPerChannel, tmpRotBuffer.config.numChannels ) ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx[0], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx, mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6415,9 +6721,15 @@ static ivas_error renderMcToBinaural( hCrend = mcInput->crendWrapper->hCrend; /* call CREND */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, p_tmpRendBuffer_fx, *mcInput->base.ctx.pOutSampleRate, + getNumSubframesInBuffer( &outAudio, *mcInput->base.ctx.pOutSampleRate ), 0 ) ), + IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, p_tmpRendBuffer_fx, *mcInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *mcInput->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6515,7 +6827,11 @@ static ivas_error renderMcToBinauralRoom( set32_fx( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, +#ifdef SPLIT_REND_WITH_HEAD_ROT + mcInput->rot_gains_prev_fx[0], +#else mcInput->rot_gains_prev_fx, +#endif mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) ) { @@ -6536,9 +6852,15 @@ static ivas_error renderMcToBinauralRoom( hCrend = mcInput->crendWrapper->hCrend; /* call CREND */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, p_tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate, + getNumSubframesInBuffer( &outAudio, *mcInput->base.ctx.pOutSampleRate ), 0 ) ), + IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, p_tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *mcInput->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6550,7 +6872,11 @@ static ivas_error renderMcToBinauralRoom( accumulate2dArrayToBuffer_fx( tmpRendBuffer, &outAudio ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6609,7 +6935,11 @@ static ivas_error renderMcCustomLsToBinauralRoom( set32_fx( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, +#ifdef SPLIT_REND_WITH_HEAD_ROT + mcInput->rot_gains_prev_fx[0], +#else mcInput->rot_gains_prev_fx, +#endif mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) ) { @@ -6648,9 +6978,15 @@ static ivas_error renderMcCustomLsToBinauralRoom( CREND_HANDLE hCrend; hCrend = mcInput->crendWrapper->hCrend; /* call CREND */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, NULL, NULL, NULL, NULL, + p_tmpCrendBuffer, *mcInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *mcInput->base.ctx.pOutSampleRate ), 0 ) ), + IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *mcInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *mcInput->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6661,7 +6997,11 @@ static ivas_error renderMcCustomLsToBinauralRoom( accumulate2dArrayToBuffer_fx( tmpCrendBuffer, &outAudio ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6726,55 +7066,222 @@ static void renderMcToMasa( return; } -static ivas_error renderInputMc( +#ifdef SPLIT_REND_WITH_HEAD_ROT +static ivas_error renderMcToSplitBinaural( input_mc *mcInput, const AUDIO_CONFIG outConfig, IVAS_REND_AudioBuffer outAudio ) { + int16_t i, j, pos_idx; + int16_t sf; + int16_t output_frame; ivas_error error; - IVAS_REND_AudioBuffer inAudio; - error = IVAS_ERR_OK; - move32(); + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + const SPLIT_REND_WRAPPER *pSplitRendWrapper; + float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; + float tmpSplitBinauralBuffer[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + AUDIO_CONFIG inConfig; + IVAS_REND_AudioBuffer tmpRotBuffer; + COMBINED_ORIENTATION_DATA combinedOrientationDataLocal; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal; - inAudio = mcInput->base.inputBuffer; + push_wmops( "renderMcToSplitBinaural" ); + inConfig = mcInput->base.inConfig; + output_frame = mcInput->base.inputBuffer.config.numSamplesPerChannel; - IF( NE_32( mcInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) + pSplitRendWrapper = mcInput->base.ctx.pSplitRendWrapper; + pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; + + for ( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) { - return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" ); + p_tmpRendBuffer[i] = tmpRendBuffer[i]; } - mcInput->base.numNewSamplesPerChannel = 0; - move32(); - v_multc_fixed( inAudio.data_fx, mcInput->base.gain_fx, inAudio.data_fx, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); - *outAudio.pq_fact = sub( *outAudio.pq_fact, Q1 ); // reducing the Q by 1 compensating for the v_mult_fixed done - move16(); - /* set combined orientation subframe info to start info */ - ivas_combined_orientation_set_to_start_index( *( mcInput->base.ctx.pCombinedOrientationData ) ); - SWITCH( getAudioConfigType( outConfig ) ) + /* save current head positions */ + pCombinedOrientationDataLocal = *mcInput->base.ctx.pCombinedOrientationData; + combinedOrientationDataLocal = *pCombinedOrientationDataLocal; + if ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) { - case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: - renderMcToMc( mcInput, outAudio ); - BREAK; - case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: - renderMcToSba( mcInput, outAudio ); - BREAK; - case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: - SWITCH( outConfig ) + for ( sf = 1; sf < combinedOrientationDataLocal.num_subframes; ++sf ) + { + combinedOrientationDataLocal.Quaternions[sf] = combinedOrientationDataLocal.Quaternions[0]; + for ( i = 0; i < 3; i++ ) { - case IVAS_AUDIO_CONFIG_BINAURAL: - error = renderMcToBinaural( mcInput, outConfig, outAudio ); - BREAK; - case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: - case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: - IF( mcInput->base.inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) - { - error = renderMcCustomLsToBinauralRoom( mcInput, outConfig, outAudio ); - } - ELSE - { - error = renderMcToBinauralRoom( mcInput, outConfig, outAudio ); - } - BREAK; + for ( j = 0; j < 3; j++ ) + { + combinedOrientationDataLocal.Rmat[sf][i][j] = combinedOrientationDataLocal.Rmat[0][i][j]; + } + } + } + } + + /* temporary buffer for rotation in source format for CREND */ + tmpRotBuffer = mcInput->base.inputBuffer; + if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM && inConfig != IVAS_AUDIO_CONFIG_5_1 && inConfig != IVAS_AUDIO_CONFIG_7_1 ) + { + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + } + + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + /* Update head positions */ + IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; + for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + { + Quaternions_orig[i] = combinedOrientationDataLocal.Quaternions[i]; + Quaternions_abs.w = -3.0f; + Quat2EulerDegree( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/ + + Quaternions_abs.x += pMultiBinPoseData->relative_head_poses[pos_idx][0]; + Quaternions_abs.y += pMultiBinPoseData->relative_head_poses[pos_idx][1]; + Quaternions_abs.z += pMultiBinPoseData->relative_head_poses[pos_idx][2]; + combinedOrientationDataLocal.Quaternions[i] = Quaternions_abs; + QuatToRotMat( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat[i] ); + } + + if ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM || inConfig == IVAS_AUDIO_CONFIG_5_1 || inConfig == IVAS_AUDIO_CONFIG_7_1 ) + { + /* tdrend processing overview: + * 1. copy from inputBuffer to tmpRendBuffer + * 2. td_binaural_renderer_ext: inplace processing in tmpRendBuffer + * 3. copy from tmpRendBuffer to tmpSplitBinBuffer + * 4. LFE mixing + * 5. tmpSplitBinBuffer accumulated to outBuffer */ + + /* copy input to tdrend input/output buffer */ + copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); + + /* perform rotation in source format to tmpRotBuffer */ + pCombinedOrientationDataLocal = &combinedOrientationDataLocal; + + /* Render */ + if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &mcInput->tdRendWrapper : &mcInput->splitTdRendWrappers[pos_idx - 1], mcInput->base.inConfig, &mcInput->customLsInput, &pCombinedOrientationDataLocal, NULL, mcInput->hReverb, 0, /* Ism Audio Metadata Delay Sync in ms for External Renderer */ *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Copy rendered audio to tmp storage buffer. Copying directly to output would + * overwrite original audio, which is still needed for rendering next head pose. */ + mvr2r( tmpRendBuffer[0], tmpSplitBinauralBuffer[2 * pos_idx], output_frame ); + mvr2r( tmpRendBuffer[1], tmpSplitBinauralBuffer[2 * pos_idx + 1], output_frame ); + } + else + { + /* crend processing overview: + * 1. rotateFrameMc: inputBuffer to tmpRotBuffer + * 2. crend_process: tmpRotBuffer to tmpRendBuffer + * 3. copy from tmpRendBuffer to tmpSplitBinBuffer + * 4. LFE mixing + * 5. tmpSplitBinBuffer accumulated to outBuffer */ + + + /* copy input for in-place rotation */ + set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); + + /* perform rotation in source format to tmpRotBuffer */ + pCombinedOrientationDataLocal = &combinedOrientationDataLocal; + if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, mcInput->rot_gains_prev[pos_idx], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + copyBufferTo2dArray( tmpRotBuffer, tmpRendBuffer ); + + /* call CREND (rotation already performed) */ + if ( ( error = ivas_rend_crendProcessSubframe( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, + NULL, NULL, NULL, p_tmpRendBuffer, p_tmpRendBuffer, mcInput->base.inputBuffer.config.numSamplesPerChannel, *mcInput->base.ctx.pOutSampleRate, pos_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Copy rendererd audio to tmp storage buffer, Copying directly to output would + * overwrite original audio, which is still needed for rendering next head pose. */ + mvr2r( tmpRendBuffer[0], tmpSplitBinauralBuffer[2 * pos_idx], output_frame ); + mvr2r( tmpRendBuffer[1], tmpSplitBinauralBuffer[2 * pos_idx + 1], output_frame ); + } + + /* restore original headrotation data */ + for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + { + combinedOrientationDataLocal.Quaternions[i] = Quaternions_orig[i]; + } + } + + if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM && inConfig != IVAS_AUDIO_CONFIG_5_1 && inConfig != IVAS_AUDIO_CONFIG_7_1 ) + { + /* free temporary buffer for rotation in source format for CREND */ + free( tmpRotBuffer.data ); + } + + accumulate2dArrayToBuffer( tmpSplitBinauralBuffer, &outAudio ); + + if ( ( error = renderLfeToBinaural( mcInput, outConfig, outAudio ) ) != IVAS_ERR_OK ) + { + return error; + } + + pop_wmops(); + return IVAS_ERR_OK; +} +#endif + + +static ivas_error renderInputMc( + input_mc *mcInput, + const AUDIO_CONFIG outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + ivas_error error; + IVAS_REND_AudioBuffer inAudio; + error = IVAS_ERR_OK; + move32(); + + inAudio = mcInput->base.inputBuffer; + + IF( NE_32( mcInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" ); + } + mcInput->base.numNewSamplesPerChannel = 0; + move32(); + v_multc_fixed( inAudio.data_fx, mcInput->base.gain_fx, inAudio.data_fx, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels ); + *outAudio.pq_fact = sub( *outAudio.pq_fact, Q1 ); // reducing the Q by 1 compensating for the v_mult_fixed done + move16(); + /* set combined orientation subframe info to start info */ + ivas_combined_orientation_set_to_start_index( *( mcInput->base.ctx.pCombinedOrientationData ) ); + + SWITCH( getAudioConfigType( outConfig ) ) + { + case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: + renderMcToMc( mcInput, outAudio ); + BREAK; + case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: + renderMcToSba( mcInput, outAudio ); + BREAK; + case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: + SWITCH( outConfig ) + { + case IVAS_AUDIO_CONFIG_BINAURAL: + error = renderMcToBinaural( mcInput, outConfig, outAudio ); + BREAK; + case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR: + case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB: + IF( mcInput->base.inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) + { + error = renderMcCustomLsToBinauralRoom( mcInput, outConfig, outAudio ); + } + ELSE + { + error = renderMcToBinauralRoom( mcInput, outConfig, outAudio ); + } + BREAK; +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + error = renderMcToSplitBinaural( mcInput, outConfig, outAudio ); + break; +#endif default: return IVAS_ERR_INVALID_OUTPUT_FORMAT; } @@ -6850,6 +7357,170 @@ static void renderSbaToSba( pop_wmops(); return; } + + +#ifdef SPLIT_REND_WITH_HEAD_ROT + +static ivas_error renderSbaToMultiBinaural( + input_sba *sbaInput, + const AUDIO_CONFIG outConfig, + float out[][L_FRAME48k] ) +{ + float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; + int16_t sf; + int16_t i, j, pos_idx; + COMBINED_ORIENTATION_DATA combinedOrientationDataLocal; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal; + ivas_error error; + IVAS_REND_AudioBuffer tmpRotBuffer; + const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; + + for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + { + p_tmpCrendBuffer[i] = tmpCrendBuffer[i]; + } + push_wmops( "renderSbaToMultiBinaural" ); + pMultiBinPoseData = &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData; + + pCombinedOrientationDataLocal = *sbaInput->base.ctx.pCombinedOrientationData; + combinedOrientationDataLocal = *pCombinedOrientationDataLocal; + if ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + { + for ( sf = 1; sf < combinedOrientationDataLocal.num_subframes; sf++ ) + { + combinedOrientationDataLocal.Quaternions[sf] = combinedOrientationDataLocal.Quaternions[0]; + for ( i = 0; i < 3; i++ ) + { + for ( j = 0; j < 3; j++ ) + { + combinedOrientationDataLocal.Rmat[sf][i][j] = combinedOrientationDataLocal.Rmat[0][i][j]; + } + } + } + } + + tmpRotBuffer = sbaInput->base.inputBuffer; + tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + + for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + { + IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; + for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + { + Quaternions_orig[i] = combinedOrientationDataLocal.Quaternions[i]; + Quaternions_abs.w = -3.0f; + Quat2EulerDegree( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/ + + Quaternions_abs.x += pMultiBinPoseData->relative_head_poses[pos_idx][0]; + Quaternions_abs.y += pMultiBinPoseData->relative_head_poses[pos_idx][1]; + Quaternions_abs.z += pMultiBinPoseData->relative_head_poses[pos_idx][2]; + combinedOrientationDataLocal.Quaternions[i] = Quaternions_abs; + QuatToRotMat( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat[i] ); + } + + + /* copy input for in-place rotation */ + mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); + + pCombinedOrientationDataLocal = &combinedOrientationDataLocal; + + if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, sbaInput->rot_gains_prev[pos_idx], tmpRotBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + copyBufferTo2dArray( tmpRotBuffer, tmpCrendBuffer ); + + assert( sbaInput->crendWrapper->hCrend[0]->hReverb == NULL ); + + /* call CREND */ + if ( ( error = ivas_rend_crendProcessSubframe( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, + NULL, NULL, NULL, p_tmpCrendBuffer, p_tmpCrendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, *sbaInput->base.ctx.pOutSampleRate, pos_idx ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + { + combinedOrientationDataLocal.Quaternions[i] = Quaternions_orig[i]; + } + + + /* move to output */ + for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + mvr2r( tmpCrendBuffer[i], out[pos_idx * BINAURAL_CHANNELS + i], tmpRotBuffer.config.numSamplesPerChannel ); + } + } + + free( tmpRotBuffer.data ); + + pop_wmops(); + return IVAS_ERR_OK; +} + + +static ivas_error renderSbaToMultiBinauralCldfb( + input_sba *sbaInput, + float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const int16_t low_res_pre_rend_rot, + const int16_t num_subframes ) +{ + float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + + copyBufferToCLDFBarray( sbaInput->base.inputBuffer, Cldfb_RealBuffer, Cldfb_ImagBuffer ); + + ivas_rend_CldfbMultiBinRendProcess( sbaInput->cldfbRendWrapper.hCldfbRend, sbaInput->base.ctx.pCombinedOrientationData, &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData, + Cldfb_RealBuffer, Cldfb_ImagBuffer, Cldfb_Out_Real, Cldfb_Out_Imag, low_res_pre_rend_rot, num_subframes ); + + return IVAS_ERR_OK; +} + + +static ivas_error renderSbaToSplitBinaural( + input_sba *sbaInput, + const AUDIO_CONFIG outConfig, + IVAS_REND_AudioBuffer outAudio ) +{ + float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + ivas_error error; + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + int16_t low_res_pre_rend_rot; + + low_res_pre_rend_rot = 1; + + push_wmops( "renderSbaToSplitBinaural" ); + error = IVAS_ERR_OK; + + if ( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + { + if ( ( renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, low_res_pre_rend_rot, + getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + } + else + { + if ( ( renderSbaToMultiBinaural( sbaInput, outConfig, tmpCrendBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); + } + + pop_wmops(); + return error; +} +#endif + static ivas_error renderSbaToBinaural( input_sba *sbaInput, const AUDIO_CONFIG outConfig, @@ -6865,6 +7536,23 @@ static ivas_error renderSbaToBinaural( Word32 *output_fx[MAX_OUTPUT_CHANNELS]; push_wmops( "renderSbaToBinaural" ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + { + float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + + if ( ( error = renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, 0, + getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ) != IVAS_ERR_OK ) + { + return error; + } + + accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + } + else +#endif { FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) @@ -6897,12 +7585,22 @@ static ivas_error renderSbaToBinaural( Copy32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, i_mult( tmpRotBuffer.config.numChannels, tmpRotBuffer.config.numSamplesPerChannel ) ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_16( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, + sbaInput->base.ctx.pCombinedOrientationData, sbaInput->rot_gains_prev_fx[0], tmpRotBuffer ) ), + IVAS_ERR_OK ) ) + { + return error; + } +#else IF( NE_16( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->base.ctx.pCombinedOrientationData, sbaInput->rot_gains_prev_fx, tmpRotBuffer ) ), IVAS_ERR_OK ) ) { return error; } +#endif copyBufferTo2dArray_fx( tmpRotBuffer, output_buffer_fx ); free( tmpRotBuffer.data_fx ); @@ -6916,9 +7614,15 @@ static ivas_error renderSbaToBinaural( hCrend = sbaInput->crendWrapper->hCrend; /* call CREND */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, output_fx, *sbaInput->base.ctx.pOutSampleRate, + getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ), 0 ) ), + IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, output_fx, *sbaInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6994,7 +7698,11 @@ static ivas_error renderSbaToBinauralRoom( IF( NE_32( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->base.ctx.pCombinedOrientationData, +#ifdef SPLIT_REND_WITH_HEAD_ROT + sbaInput->rot_gains_prev_fx[0], +#else sbaInput->rot_gains_prev_fx, +#endif tmpRotBuffer ) ), IVAS_ERR_OK ) ) { @@ -7031,10 +7739,17 @@ static ivas_error renderSbaToBinauralRoom( // Porting Crend_process function /* call CREND */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, + NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate, + getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ), 0 ) ), + IVAS_ERR_OK ) ) +#else IF( NE_32( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -7076,11 +7791,20 @@ static ivas_error renderInputSba( { ivas_error error; IVAS_REND_AudioBuffer inAudio; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t cldfb2tdSampleFact; +#endif error = IVAS_ERR_OK; move32(); inAudio = sbaInput->base.inputBuffer; +#ifdef SPLIT_REND_WITH_HEAD_ROT + cldfb2tdSampleFact = outAudio.config.is_cldfb ? 2 : 1; + if ( ( sbaInput->base.numNewSamplesPerChannel * cldfb2tdSampleFact != outAudio.config.numSamplesPerChannel ) && + ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else IF( NE_32( sbaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" ); } @@ -7098,6 +7822,12 @@ static ivas_error renderInputSba( SWITCH( getAudioConfigType( outConfig ) ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + error = renderSbaToSplitBinaural( sbaInput, outConfig, outAudio ); + break; +#endif case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: renderSbaToMc( sbaInput, outAudio ); BREAK; @@ -7436,6 +8166,11 @@ static ivas_error renderInputMasa( Word16 maxBin; Word32 *tmpBuffer_fx[MAX_OUTPUT_CHANNELS]; Word32 tmpBuffer_buff_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t cldfb2tdSampleFact; + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; +#endif IF( !masaInput->metadataHasBeenFed ) { @@ -7443,7 +8178,14 @@ static ivas_error renderInputMasa( } inAudio = masaInput->base.inputBuffer; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + cldfb2tdSampleFact = outAudio.config.is_cldfb ? 2 : 1; + if ( ( masaInput->base.numNewSamplesPerChannel * cldfb2tdSampleFact != outAudio.config.numSamplesPerChannel ) && + ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else IF( NE_32( masaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" ); } @@ -7480,58 +8222,94 @@ static ivas_error renderInputMasa( num_subframes = BASOP_Util_Divide3232_Scale( L_mult0( masaInput->base.inputBuffer.config.numSamplesPerChannel, IVAS_NUM_FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ), *masaInput->base.ctx.pOutSampleRate, &exp ); num_subframes = shr( num_subframes, sub( 15, exp ) ); /* Q0 */ - SWITCH( masaInput->hMasaExtRend->renderer_type ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) { - case RENDERER_DIRAC: - - copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); - intermidiate_ext_dirac_render( masaInput->hMasaExtRend, 1 ); - FOR( ch = 0; ch < masaInput->hMasaExtRend->hDirACRend->hOutSetup.nchan_out_woLFE + masaInput->hMasaExtRend->hDirACRend->hOutSetup.num_lfe; ch++ ) - { - masaInput->hMasaExtRend->cldfbAnaRend[0]->Q_cldfb_state = Q11; - move16(); - } - FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + /* split rendering. use the combined of the first subframe in all subframes */ + int16_t sf, i, j; + COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; + pCombinedOrientationData = *masaInput->base.ctx.pCombinedOrientationData; + for ( sf = 1; sf < pCombinedOrientationData->num_subframes; sf++ ) + { + pCombinedOrientationData->Quaternions[sf] = pCombinedOrientationData->Quaternions[0]; + for ( i = 0; i < 3; i++ ) { - Scale_sig32( tmpBuffer_buff_fx[ch], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + for ( j = 0; j < 3; j++ ) + { + pCombinedOrientationData->Rmat[sf][i][j] = pCombinedOrientationData->Rmat[0][i][j]; + } } + } - scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); - ivas_masa_ext_dirac_render_fx( masaInput->hMasaExtRend, tmpBuffer_fx, num_subframes ); + ivas_masa_ext_rend_parambin_render( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, num_subframes, masaInput->base.ctx.pSplitRendWrapper, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); - *outAudio.pq_fact = Q11; - move16(); + accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + } + else + { + /* non-split path */ +#endif + SWITCH( masaInput->hMasaExtRend->renderer_type ) + { + case RENDERER_DIRAC: - FOR( ch = 0; ch < masaInput->hMasaExtRend->hDirACRend->hOutSetup.nchan_out_woLFE + masaInput->hMasaExtRend->hDirACRend->hOutSetup.num_lfe; ch++ ) - { - scale_sig32( masaInput->hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, masaInput->hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, masaInput->hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); /* Q11 */ - masaInput->hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11; + copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); + intermidiate_ext_dirac_render( masaInput->hMasaExtRend, 1 ); + FOR( ch = 0; ch < masaInput->hMasaExtRend->hDirACRend->hOutSetup.nchan_out_woLFE + masaInput->hMasaExtRend->hDirACRend->hOutSetup.num_lfe; ch++ ) + { + masaInput->hMasaExtRend->cldfbAnaRend[0]->Q_cldfb_state = Q11; + move16(); + } + FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + { + Scale_sig32( tmpBuffer_buff_fx[ch], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + } + + scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + + ivas_masa_ext_dirac_render_fx( masaInput->hMasaExtRend, tmpBuffer_fx, num_subframes ); + + *outAudio.pq_fact = Q11; move16(); - } - intermidiate_ext_dirac_render( masaInput->hMasaExtRend, 0 ); - BREAK; - case RENDERER_STEREO_PARAMETRIC: - case RENDERER_BINAURAL_PARAMETRIC: - case RENDERER_BINAURAL_PARAMETRIC_ROOM: + FOR( ch = 0; ch < masaInput->hMasaExtRend->hDirACRend->hOutSetup.nchan_out_woLFE + masaInput->hMasaExtRend->hDirACRend->hOutSetup.num_lfe; ch++ ) + { + scale_sig32( masaInput->hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, masaInput->hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, masaInput->hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); /* Q11 */ + masaInput->hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11; + move16(); + } - copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); + intermidiate_ext_dirac_render( masaInput->hMasaExtRend, 0 ); + BREAK; + case RENDERER_STEREO_PARAMETRIC: + case RENDERER_BINAURAL_PARAMETRIC: + case RENDERER_BINAURAL_PARAMETRIC_ROOM: - Scale_sig32( tmpBuffer_buff_fx[0], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ - Scale_sig32( tmpBuffer_buff_fx[1], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); - scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) ); + Scale_sig32( tmpBuffer_buff_fx[0], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + Scale_sig32( tmpBuffer_buff_fx[1], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + ivas_masa_ext_rend_parambin_render_fx( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer_fx, num_subframes, NULL, NULL, NULL ); +#else ivas_masa_ext_rend_parambin_render_fx( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer_fx, num_subframes ); - *outAudio.pq_fact = Q11; - move16(); - BREAK; - case RENDERER_DISABLE: - BREAK; /* This happens for 1TC MASA to MONO where we just copy input transport to output */ - default: - return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) ); +#endif + *outAudio.pq_fact = Q11; + move16(); + BREAK; + case RENDERER_DISABLE: + BREAK; /* This happens for 1TC MASA to MONO where we just copy input transport to output */ + default: + return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) ); + } +#ifdef SPLIT_REND_WITH_HEAD_ROT } +#endif accumulate2dArrayToBuffer_fx( tmpBuffer_buff_fx, &outAudio ); } @@ -7763,12 +8541,21 @@ ivas_error IVAS_REND_SetIsmMetadataDelay( *-------------------------------------------------------------------*/ static ivas_error getSamplesInternal( - IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ +#ifdef SPLIT_REND_WITH_HEAD_ROT + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */, + IVAS_REND_BitstreamBuffer *hBits /*i/o: buffer for input/output bitstream. Needed in split rendering mode*/ +#else IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ +#endif ) { ivas_error error; Word16 numOutChannels; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t cldfb2tdSampleFact; + IVAS_REND_AudioBuffer outAudioOrig; +#endif /* Validate function arguments */ test(); IF( hIvasRend == NULL || outAudio.data_fx == NULL ) @@ -7777,7 +8564,14 @@ static ivas_error getSamplesInternal( } test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + cldfb2tdSampleFact = ( outAudio.config.is_cldfb ) ? 2 : 1; + + if ( outAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 0 ) || + ( ( MAX_BUFFER_LENGTH_PER_CHANNEL * cldfb2tdSampleFact ) < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 1 ) ) +#else IF( outAudio.config.numSamplesPerChannel <= 0 || LT_16( MAX_BUFFER_LENGTH_PER_CHANNEL, outAudio.config.numSamplesPerChannel ) ) +#endif { return IVAS_ERR_INVALID_BUFFER_SIZE; } @@ -7789,8 +8583,15 @@ static ivas_error getSamplesInternal( } test(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && + ( outAudio.config.numSamplesPerChannel * 1000 / cldfb2tdSampleFact ) != ( hIvasRend->num_subframes * BINAURAL_RENDERING_FRAME_SIZE_MS ) * hIvasRend->sampleRateOut ) +#else IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && NE_32( L_mult0( outAudio.config.numSamplesPerChannel, 1000 ), imult3216( hIvasRend->sampleRateOut, i_mult( hIvasRend->num_subframes, BINAURAL_RENDERING_FRAME_SIZE_MS ) ) ) ) +#endif { return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" ); } @@ -7864,41 +8665,256 @@ static ivas_error getSamplesInternal( } } - IF( NE_32( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ), IVAS_ERR_OK ) ) - { - return error; - } + IF( NE_32( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ), IVAS_ERR_OK ) ) + { + return error; + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( numOutChannels != outAudio.config.numChannels && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) +#else + IF( NE_16( numOutChannels, outAudio.config.numChannels ) ) +#endif + { + return IVAS_ERR_WRONG_NUM_CHANNELS; + } + + /* Clear original output buffer */ + set32_fx( outAudio.data_fx, 0, imult1616( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ) ); + +#ifdef SPLIT_REND_WITH_HEAD_ROT + outAudioOrig = outAudio; + /* Use internal buffer if outputting split rendering bitstream */ + if ( ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || + ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + int16_t num_poses_orig; + num_poses_orig = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; + outAudio = hIvasRend->splitRendEncBuffer; + Word16 i, q_factor = Q22; + + ISAR_PRE_REND_GetMultiBinPoseData( &hIvasRend->hRendererConfig->split_rend_config, &hIvasRend->splitRendWrapper.multiBinPoseData, hIvasRend->headRotData.sr_pose_pred_axis ); + + FOR( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses[i][0] = fixedToFloat( hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses_fx[i][0], q_factor ); + hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses[i][1] = fixedToFloat( hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses_fx[i][1], q_factor ); + hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses[i][2] = fixedToFloat( hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses_fx[i][2], q_factor ); + } + assert( num_poses_orig == hIvasRend->splitRendWrapper.multiBinPoseData.num_poses && "number of poses should not change dynamically" ); + + /* Clear output buffer for split rendering bitstream */ + set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); + } +#endif + + IF( NE_32( ( error = renderActiveInputsIsm( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) + { + return error; + } + IF( NE_32( ( error = renderActiveInputsMc( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) + { + return error; + } + IF( NE_32( ( error = renderActiveInputsSba( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) + { + return error; + } + IF( NE_32( ( error = renderActiveInputsMasa( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) + { + return error; + } + + test(); + test(); + +#ifndef SPLIT_REND_WITH_HEAD_ROT + + Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); + limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact ); +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + ISAR_SPLIT_REND_BITS_DATA bits; + int16_t cldfb_in_flag; + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + for ( int i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + { + for ( int j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + for ( int k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + { + Cldfb_RealBuffer_Binaural[i][j][k] = 0; + Cldfb_ImagBuffer_Binaural[i][j][k] = 0; + } + } + } + int16_t ch; + int16_t i, ro_md_flag; + float *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + { + tmpBinaural[ch] = tmpBinaural_buff[ch]; + } + + if ( outAudio.config.is_cldfb == 1 ) + { + cldfb_in_flag = 1; + copyBufferToCLDFBarray( outAudio, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); + } + else + { + cldfb_in_flag = 0; + copyBufferTo2dArray( outAudio, tmpBinaural_buff ); + } + + /* Encode split rendering bitstream */ + convertBitsBufferToInternalBitsBuff( *hBits, &bits ); + + ro_md_flag = 0; + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + ro_md_flag = 1; + break; + } + } + Word16 j; + Word16 q, q1 = 31, q2 = 31, Q_buff; + Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word32 *pOutput_fx[CLDFB_NO_COL_MAX]; + Word32 output_fx[CLDFB_NO_COL_MAX][L_FRAME48k]; + Word16 Q_out[CLDFB_NO_COL_MAX]; + Q_out[0] = 31; + for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) + { + pOutput_fx[i] = &( output_fx[i][0] ); + } + Word16 num_poses = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; + for ( i = 0; i < 16; i++ ) + { + for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + q = Q_factor_arrL( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ); + q1 = s_min( q1, q ); + q = Q_factor_arrL( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ); + q2 = s_min( q2, q ); + } + } + Q_buff = s_min( q1, q2 ); + for ( i = 0; i < 16; i++ ) + { + for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + floatToFixed_arrL( Cldfb_RealBuffer_Binaural[i][j], Cldfb_RealBuffer_Binaural_fx[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL( Cldfb_ImagBuffer_Binaural[i][j], Cldfb_ImagBuffer_Binaural_fx[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + } + } + IF( EQ_16( cldfb_in_flag, 0 ) ) + { + /*TD input*/ + /*if CLDFB handles have been allocated then assume valid multi binaural input in out[][] buffer and perform CLDFB analysis*/ + /* local float2fix, to be removed */ + num_poses = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; + if ( hIvasRend->splitRendWrapper.hLc3plusEnc != NULL ) + { + Word16 frame_size_lc3 = (Word16) ( ( hIvasRend->splitRendWrapper.hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ) + hIvasRend->splitRendWrapper.lc3plusDelaySamples ); + + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + Q_out[0] = s_min( Q_out[0], Q_factor_arrL( hIvasRend->splitRendWrapper.lc3plusDelayBuffers[i], frame_size_lc3 ) ); + } + } + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + Q_out[0] = s_min( Q_out[0], Q_factor_arrL( tmpBinaural[i], L_FRAME48k ) ); + } + // printf("%d\n", Q_sig); + if ( hIvasRend->splitRendWrapper.hLc3plusEnc != NULL ) + { + Word16 frame_size_lc3 = (Word16) ( ( hIvasRend->splitRendWrapper.hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ) + hIvasRend->splitRendWrapper.lc3plusDelaySamples ); + + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + floatToFixed_arrL( hIvasRend->splitRendWrapper.lc3plusDelayBuffers[i], hIvasRend->splitRendWrapper.lc3plusDelayBuffers_fx[i], Q_out[0], frame_size_lc3 ); + } + } + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + floatToFixed_arrL( tmpBinaural[i], pOutput_fx[i], Q_out[0], L_FRAME48k ); + } + } + if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hIvasRend->splitRendWrapper, hIvasRend->headRotData.headPositions[0], hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, hIvasRend->hRendererConfig->split_rend_config.codec, +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms, +#endif + hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, + &bits, Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, pOutput_fx, 1, cldfb_in_flag, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, ro_md_flag, Q_buff, &Q_out[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + IF( EQ_16( cldfb_in_flag, 0 ) ) + { + if ( hIvasRend->splitRendWrapper.hLc3plusEnc != NULL ) + { + Word16 frame_size_lc3 = (Word16) ( ( hIvasRend->splitRendWrapper.hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ) + hIvasRend->splitRendWrapper.lc3plusDelaySamples ); + +#ifdef DUMP_LC3_DELAY_OUT + FILE *fp = fopen( "ref_lc3delay.txt", "ab" ); +#endif + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) + { + fixedToFloat_arrL( hIvasRend->splitRendWrapper.lc3plusDelayBuffers_fx[i], hIvasRend->splitRendWrapper.lc3plusDelayBuffers[i], Q_out[0], frame_size_lc3 ); +#ifdef DUMP_LC3_DELAY_OUT + for ( Word16 j = 0; j < frame_size_lc3; j++ ) + { + fprintf( fp, "%f\n", hSplitBin->lc3plusDelayBuffers[i][j] ); + } +#endif + } +#ifdef DUMP_LC3_DELAY_OUT + fclose( fp ); +#endif + } + } + + Word16 pcm_out_flag = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; + IF( NE_16( pcm_out_flag, 0 ) && ( NE_16( cldfb_in_flag, 0 ) ) ) + { + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + fixedToFloat_arrL( pOutput_fx[ch], tmpBinaural[ch], Q_out[ch], hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX ); + + fixedToFloat_arrL( hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->cldfb_state, hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->Q_split, hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->p_filter_length ); + } + } + - IF( NE_16( numOutChannels, outAudio.config.numChannels ) ) - { - return IVAS_ERR_WRONG_NUM_CHANNELS; - } + convertInternalBitsBuffToBitsBuffer( hBits, bits ); - /* Clear original output buffer */ - set32_fx( outAudio.data_fx, 0, imult1616( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ) ); + /* reset to outAudioOrig in case of PCM output */ + outAudio = outAudioOrig; - IF( NE_32( ( error = renderActiveInputsIsm( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) - { - return error; - } - IF( NE_32( ( error = renderActiveInputsMc( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) - { - return error; - } - IF( NE_32( ( error = renderActiveInputsSba( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) - { - return error; + if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + accumulate2dArrayToBuffer( tmpBinaural_buff, &outAudio ); + } } - IF( NE_32( ( error = renderActiveInputsMasa( hIvasRend, outAudio ) ), IVAS_ERR_OK ) ) +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( outAudio.config.is_cldfb == 0 ) { - return error; + Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); + limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact ); } - - test(); - test(); - - Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); - limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact ); +#endif /* update global cominbed orientation start index */ ivas_combined_orientation_update_start_index( hIvasRend->hCombinedOrientationData, outAudio.config.numSamplesPerChannel ); @@ -7918,9 +8934,71 @@ ivas_error IVAS_REND_GetSamples( ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + return getSamplesInternal( hIvasRend, outAudio, NULL ); +#else return getSamplesInternal( hIvasRend, outAudio ); +#endif +} + +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-------------------------------------------------------------------* + * IVAS_REND_GetSplitBinauralBitstream() + * + * + *-------------------------------------------------------------------*/ + +ivas_error +IVAS_REND_GetSplitBinauralBitstream( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio, /* i/o: buffer for output audio */ + IVAS_REND_BitstreamBuffer *hBits /* o : buffer for output bitstream */ +) +{ + int16_t cldfb_in_flag; + + cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); + hIvasRend->splitRendEncBuffer.config.is_cldfb = cldfb_in_flag; + if ( hIvasRend->hRendererConfig->split_rend_config.dof == 0 || hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) + { + hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = outAudio.config.numSamplesPerChannel; + } + else + { + hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = (int16_t) ( hIvasRend->sampleRateOut / FRAMES_PER_SEC ); + } + hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel *= cldfb_in_flag ? 2 : 1; + + /* hIvasRend->splitRendEncBuffer used for BINAURAL_SPLIT_CODED output + outAudio used for BINAURAL_SPLIT_PCM output */ + return getSamplesInternal( hIvasRend, outAudio, hBits ); +} + +ivas_error IVAS_REND_GetSplitRendBitstreamHeader( + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + ISAR_SPLIT_REND_CODEC *pCodec, /* o: pointer to codec setting */ + ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o: pointer to pose correction mode */ + int16_t *pCodec_frame_size_ms /* o: pointer to codec frame size setting */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + , + int16_t *pIsar_frame_size_ms /* o: pointer to isar frame size setting */ +#endif +) +{ + if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL ) + { + return IVAS_ERR_UNEXPECTED_NULL_POINTER; + } + *pCodec = hIvasRend->hRendererConfig->split_rend_config.codec; + *pCodec_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + *pIsar_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms; +#endif + *poseCorrection = hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode; + return IVAS_ERR_OK; } +#endif /*-------------------------------------------------------------------* * IVAS_REND_Close() @@ -7972,6 +9050,11 @@ void IVAS_REND_Close( ivas_limiter_close_fx( &hIvasRend->hLimiter ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* Split binaural rendering */ + ISAR_PRE_REND_close( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer ); +#endif + closeHeadRotation( hIvasRend ); @@ -7984,6 +9067,126 @@ void IVAS_REND_Close( return; } +#ifdef SPLIT_REND_WITH_HEAD_ROT +/*-------------------------------------------------------------------* + * IVAS_REND_openCldfb() + * + * + *-------------------------------------------------------------------*/ + +ivas_error +IVAS_REND_openCldfb( + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS], + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_OUTPUT_CHANNELS], + const int16_t num_in_chs, + const int16_t num_out_chs, + const int32_t output_Fs ) +{ + int16_t n; + ivas_error error; + + for ( n = 0; n < num_in_chs; n++ ) + { + if ( ( error = openCldfb( &( cldfbAna[n] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; n < IVAS_MAX_INPUT_CHANNELS; n++ ) + { + cldfbAna[n] = NULL; + } + + for ( n = 0; n < num_out_chs; n++ ) + { + if ( ( error = openCldfb( &( cldfbSyn[n] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + for ( ; n < IVAS_MAX_OUTPUT_CHANNELS; n++ ) + { + cldfbSyn[n] = NULL; + } + + return IVAS_ERR_OK; +} + +/*-------------------------------------------------------------------* + * IVAS_REND_closeCldfb() + * + * + *-------------------------------------------------------------------*/ + +void IVAS_REND_closeCldfb( + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS], + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_OUTPUT_CHANNELS] ) +{ + int16_t n; + + for ( n = 0; n < IVAS_MAX_INPUT_CHANNELS; n++ ) + { + if ( cldfbAna[n] != NULL ) + { + deleteCldfb( &( cldfbAna[n] ) ); + cldfbAna[n] = NULL; + } + } + + for ( n = 0; n < IVAS_MAX_OUTPUT_CHANNELS; n++ ) + { + if ( cldfbSyn[n] != NULL ) + { + deleteCldfb( &( cldfbSyn[n] ) ); + cldfbSyn[n] = NULL; + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_cldfbSynthesis_wrapper() + * + * + *-------------------------------------------------------------------*/ + +void IVAS_REND_cldfbAnalysis_ts_wrapper( + const float *timeIn, /* i : time buffer */ + float realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ + float imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ + const int16_t samplesToProcess, /* i : samples to process */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filterbank state */ +) +{ + cldfbAnalysis_ts( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb ); + + return; +} + + +/*-------------------------------------------------------------------* + * IVAS_REND_cldfbSynthesis_wrapper() + * + * + *-------------------------------------------------------------------*/ + +void IVAS_REND_cldfbSynthesis_wrapper( + float **realBuffer, /* i : real values */ + float **imagBuffer, /* i : imag values */ + float *timeOut, /* o : output time domain samples */ + const int16_t samplesToProcess, /* i : number of processed samples */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filter bank state */ +) +{ + cldfbSynthesis( realBuffer, imagBuffer, timeOut, samplesToProcess, h_cldfb ); + + return; +} +#endif + + static ivas_error ivas_masa_ext_rend_dirac_rend_init( input_masa *inputMasa ) { @@ -8426,6 +9629,10 @@ static ivas_error ivas_masa_ext_rend_parambin_init( Word16 tmpFloat_fx; ivas_error error; Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX]; +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; +#endif + Word16 tmp; Word16 tmp_e; Word16 tmp2; @@ -8443,144 +9650,165 @@ static ivas_error ivas_masa_ext_rend_parambin_init( renderer_type = inputMasa->hMasaExtRend->renderer_type; move32(); - hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin; - - /* Init assumes that no reconfiguration is required in external renderer. Instead, free and rebuild whole rendering. */ - IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( pos_idx = 0; pos_idx < inputMasa->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses; pos_idx++ ) { - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); - } - - hDiracDecBin->hTdDecorr = NULL; - hDiracDecBin->hReverb = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; - hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; - hDiracDecBin->hDiffuseDist = NULL; /* Not used in external renderer */ - hDiracDecBin->useTdDecorr = 0; /* Always use frequency domain decorrelator in external renderer */ - move16(); + hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin[pos_idx]; +#else + hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin; +#endif - FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) - { - FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) + /* Init assumes that no reconfiguration is required in external renderer. Instead, free and rebuild whole rendering. */ + IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL ) { - set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins ); - set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins ); + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " ); } - FOR( k = 0; k < BINAURAL_CHANNELS; k++ ) - { - set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins ); - set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins ); - } - hDiracDecBin->q_processMtx = Q15; - hDiracDecBin->q_processMtxSCCR = Q15; - hDiracDecBin->q_processMtxPrev = Q15; - hDiracDecBin->q_processMtxPrevSCCR = Q15; - hDiracDecBin->q_processMtxDec = Q15; - hDiracDecBin->q_processMtxDecPrev = Q15; - move16(); - move16(); - move16(); - move16(); - move16(); + hDiracDecBin->hTdDecorr = NULL; + hDiracDecBin->hReverb = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_params = NULL; + hDiracDecBin->h_freq_domain_decorr_ap_state = NULL; + hDiracDecBin->hDiffuseDist = NULL; /* Not used in external renderer */ + hDiracDecBin->useTdDecorr = 0; /* Always use frequency domain decorrelator in external renderer */ move16(); - set_zero_fx( hDiracDecBin->ChEnePrev_fx[j], nBins ); - set_zero_fx( hDiracDecBin->ChEneOutPrev_fx[j], nBins ); - set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins ); - set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins ); - } - set_zero_fx( hDiracDecBin->ChCrossRePrev_fx, nBins ); - set_zero_fx( hDiracDecBin->ChCrossImPrev_fx, nBins ); - set_zero_fx( hDiracDecBin->ChCrossReOutPrev_fx, nBins ); - set_zero_fx( hDiracDecBin->ChCrossImOutPrev_fx, nBins ); - set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins ); - set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins ); - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; - move16(); - FOR( bin = 0; bin < nBins; bin++ ) - { - binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/ - /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ - tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, L_shl( 2700, Q15 ), &tmp_e ); - IF( tmp_e < 0 ) + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) { - tmp = shl( tmp, tmp_e ); /*q15*/ - tmp_e = 0; + FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ ) + { + set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins ); + } + + FOR( k = 0; k < BINAURAL_CHANNELS; k++ ) + { + set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins ); + set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins ); + } + hDiracDecBin->q_processMtx = Q15; + hDiracDecBin->q_processMtxSCCR = Q15; + hDiracDecBin->q_processMtxPrev = Q15; + hDiracDecBin->q_processMtxPrevSCCR = Q15; + hDiracDecBin->q_processMtxDec = Q15; + hDiracDecBin->q_processMtxDecPrev = Q15; + move16(); + move16(); + move16(); move16(); + move16(); + move16(); + set_zero_fx( hDiracDecBin->ChEnePrev_fx[j], nBins ); + set_zero_fx( hDiracDecBin->ChEneOutPrev_fx[j], nBins ); + set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins ); + set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins ); + } + set_zero_fx( hDiracDecBin->ChCrossRePrev_fx, nBins ); + set_zero_fx( hDiracDecBin->ChCrossImPrev_fx, nBins ); + set_zero_fx( hDiracDecBin->ChCrossReOutPrev_fx, nBins ); + set_zero_fx( hDiracDecBin->ChCrossImOutPrev_fx, nBins ); + set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins ); + set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins ); + hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0; + move16(); + + FOR( bin = 0; bin < nBins; bin++ ) + { + binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/ + /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */ + tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, L_shl( 2700, Q15 ), &tmp_e ); + IF( tmp_e < 0 ) + { + tmp = shl( tmp, tmp_e ); /*q15*/ + tmp_e = 0; + move16(); + } + tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q30*/ + tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); //*binCenterFreq_fx * EVS_PI / 550.0f*/ + hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ + hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); /* Q31 */ + move32(); + move32(); } - tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/; /*Q30*/ - tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); //*binCenterFreq_fx * EVS_PI / 550.0f*/ - hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ - hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 ); /* Q31 */ - move32(); - move32(); - } - /* No SPAR in external renderer so set directive diffuse field coherence tables to zero */ - set_zero_fx( hDiracDecBin->diffuseFieldCoherenceX_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS ); - set_zero_fx( hDiracDecBin->diffuseFieldCoherenceY_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS ); - set_zero_fx( hDiracDecBin->diffuseFieldCoherenceZ_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS ); + /* No SPAR in external renderer so set directive diffuse field coherence tables to zero */ + set_zero_fx( hDiracDecBin->diffuseFieldCoherenceX_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS ); + set_zero_fx( hDiracDecBin->diffuseFieldCoherenceY_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS ); + set_zero_fx( hDiracDecBin->diffuseFieldCoherenceZ_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS ); - IF( EQ_16( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */ - { - set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28 /*1.0f Q28*/, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->q_earlyPartEneCorrection = Q28; - move16(); - hDiracDecBin->hReverb = NULL; - } - ELSE IF( EQ_16( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */ - { - Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins ); - hDiracDecBin->q_earlyPartEneCorrection = Q28; - move16(); + IF( EQ_16( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */ + { + set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28 /*1.0f Q28*/, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->q_earlyPartEneCorrection = Q28; + move16(); + hDiracDecBin->hReverb = NULL; + } + ELSE IF( EQ_16( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */ + { + Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins ); + hDiracDecBin->q_earlyPartEneCorrection = Q28; + move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */ +#else IF( hDiracDecBin->hReverb == NULL ) +#endif + { + /* Todo Philips: Room acoustics should be passed here once the underlying part works. In this case, it probably should come from render context or somewhere else suitable. */ + IF( NE_32( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, hHrtfParambin ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } + ELSE IF( EQ_16( renderer_type, RENDERER_STEREO_PARAMETRIC ) ) + { + set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28 /*1.0f Q28*/, CLDFB_NO_CHANNELS_MAX ); + hDiracDecBin->q_earlyPartEneCorrection = Q28; + move16(); + hDiracDecBin->hReverb = NULL; + hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; + move16(); + } + ELSE /* Not valid renderer type for this renderer */ + { + assert( false ); + } + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( pos_idx == 0 ) /* open decorrelator only for the main direction */ { - /* Todo Philips: Room acoustics should be passed here once the underlying part works. In this case, it probably should come from render context or somewhere else suitable. */ - IF( NE_32( ( error = ivas_binaural_reverb_open_parambin( &hDiracDecBin->hReverb, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, NULL, output_Fs, hHrtfParambin ) ), IVAS_ERR_OK ) ) +#endif + /* Always open frequency domain decorrelator */ + ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins ); + + IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), + &( hDiracDecBin->h_freq_domain_decorr_ap_state ), + nBins, + BINAURAL_CHANNELS, + BINAURAL_CHANNELS, + DIRAC_SYNTHESIS_PSD_LS, + frequency_axis_fx, + BINAURAL_CHANNELS, + output_Fs ) ), + IVAS_ERR_OK ) ) { return error; } +#ifdef SPLIT_REND_WITH_HEAD_ROT } - } - ELSE IF( EQ_16( renderer_type, RENDERER_STEREO_PARAMETRIC ) ) - { - set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28 /*1.0f Q28*/, CLDFB_NO_CHANNELS_MAX ); - hDiracDecBin->q_earlyPartEneCorrection = Q28; - move16(); - hDiracDecBin->hReverb = NULL; - hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1; +#endif + /* External renderer uses constant regularization factor */ + hDiracDecBin->reqularizationFactor_fx = 6554; /* 0.4f in Q14 */ move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + inputMasa->hMasaExtRend->hDiracDecBin[pos_idx] = hDiracDecBin; } - ELSE /* Not valid renderer type for this renderer */ - { - assert( false ); - } - - /* Always open frequency domain decorrelator */ - ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins ); - - IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ), - &( hDiracDecBin->h_freq_domain_decorr_ap_state ), - nBins, - BINAURAL_CHANNELS, - BINAURAL_CHANNELS, - DIRAC_SYNTHESIS_PSD_LS, - frequency_axis_fx, - BINAURAL_CHANNELS, - output_Fs ) ), - IVAS_ERR_OK ) ) - { - return error; - } - /* External renderer uses constant regularization factor */ - hDiracDecBin->reqularizationFactor_fx = 6554; /* 0.4f in Q14 */ - move16(); - +#else inputMasa->hMasaExtRend->hDiracDecBin = hDiracDecBin; +#endif return error; } @@ -8608,7 +9836,14 @@ static ivas_error initMasaExtRenderer( move32(); hMasaExtRend->hDirACRend = NULL; hMasaExtRend->hSpatParamRendCom = NULL; +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + hMasaExtRend->hDiracDecBin[i] = NULL; + } +#else hMasaExtRend->hDiracDecBin = NULL; +#endif hMasaExtRend->hReverb = NULL; hMasaExtRend->hHrtfParambin = NULL; hMasaExtRend->hVBAPdata = NULL; @@ -8659,6 +9894,10 @@ static ivas_error initMasaExtRenderer( BREAK; case IVAS_AUDIO_CONFIG_BINAURAL: +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: +#endif hMasaExtRend->renderer_type = RENDERER_BINAURAL_PARAMETRIC; move32(); BREAK; @@ -8776,10 +10015,21 @@ static void freeMasaExtRenderer( ivas_spat_hSpatParamRendCom_close_fx( &hMasaExtRend->hSpatParamRendCom ); } +#ifdef SPLIT_REND_WITH_HEAD_ROT + for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) + { + if ( hMasaExtRend->hDiracDecBin[i] != NULL ) + { + ivas_dirac_dec_close_binaural_data( &hMasaExtRend->hDiracDecBin[i] ); + } + } + +#else IF( hMasaExtRend->hDiracDecBin != NULL ) { ivas_dirac_dec_close_binaural_data( &hMasaExtRend->hDiracDecBin ); } +#endif IF( hMasaExtRend->hReverb != NULL ) { -- GitLab From ca4f1e55553b023a9a1d85a4a7ec61b16086ae5d Mon Sep 17 00:00:00 2001 From: rtyag Date: Mon, 3 Feb 2025 22:49:19 +1100 Subject: [PATCH 07/43] lib rend changes --- lib_com/cnst.h | 1 + lib_com/ivas_rotation_com.c | 13 +- lib_dec/ivas_binRenderer_internal.c | 21 +- lib_dec/ivas_objectRenderer_internal.c | 44 +- lib_rend/ivas_prot_rend.h | 3 +- lib_rend/lib_rend.c | 673 ++++++++++++++----------- 6 files changed, 415 insertions(+), 340 deletions(-) diff --git a/lib_com/cnst.h b/lib_com/cnst.h index e86b51472..35dc4f02a 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -596,6 +596,7 @@ enum #define FRAMES_PER_SEC 50 #define MAX_PARAM_SPATIAL_SUB_FRAMES_PER_SEC 200 //(FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES) +#define ONE_BY_SUBFRAME_LEN_MS_Q31 (429496730) #define ONE_BY_FRAMES_PER_SEC_Q31 ( 42949673 ) #define FRAMES_PER_SEC_BY_2 (FRAMES_PER_SEC >> 1) #define INV_FRAME_PER_SEC_Q15 656 diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index 9e5d1a594..fc390dfb2 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -53,7 +53,7 @@ void Euler2Quat_fx( const Word32 yaw, /* i : yaw (x) Q22 */ const Word32 pitch, /* i : pitch (y) Q22 */ const Word32 roll, /* i : roll (z) Q22 */ - IVAS_QUATERNION *quat /* o : quaternion describing the rotation Q19 */ + IVAS_QUATERNION *quat /* o : quaternion describing the rotation Q22*/ ) { Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) ); // Q14 @@ -62,15 +62,18 @@ void Euler2Quat_fx( Word16 sp = getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ); Word16 cy = getCosWord16( extract_l( L_shr_r( yaw, 10 ) ) ); Word16 sy = getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ); - quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); // Q19 + quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); // Q22 move32(); - quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); // Q19 + quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); // Q22 move32(); - quat->y_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( sr, cp ), sy ), Mpy_32_16_1( L_mult0( cr, sp ), cy ) ), 5 ); // Q19 + quat->y_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( sr, cp ), sy ), Mpy_32_16_1( L_mult0( cr, sp ), cy ) ), 5 ); // Q22 move32(); - quat->z_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( cr, cp ), sy ), Mpy_32_16_1( L_mult0( sr, sp ), cy ) ), 5 ); // Q19 + quat->z_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( cr, cp ), sy ), Mpy_32_16_1( L_mult0( sr, sp ), cy ) ), 5 ); // Q22 move32(); + quat->q_fact = Q22; + move16(); + return; } void Euler2Quat( diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 040d9bf9d..ce4dfa9c9 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -2108,6 +2108,8 @@ void ivas_rend_CldfbMultiBinRendProcess( Word32 Cldfb_ImagBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; + Word16 Q_in_orig = *Q_in; + move16(); FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { @@ -2121,20 +2123,23 @@ void ivas_rend_CldfbMultiBinRendProcess( } } - if ( ( *pCombinedOrientationData ) != NULL ) + IF( ( *pCombinedOrientationData ) != NULL ) { - if ( ( low_res_pre_rend_rot ) && ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) + IF( ( low_res_pre_rend_rot ) && ( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) ) { - ( *pCombinedOrientationData )->Quaternions[sf_idx] = ( *pCombinedOrientationData )->Quaternions[0]; - for ( i = 0; i < 3; i++ ) + Copy_Quat_fx( &( *pCombinedOrientationData )->Quaternions[0], &( *pCombinedOrientationData )->Quaternions[sf_idx] ); + + FOR( i = 0; i < 3; i++ ) { - for ( j = 0; j < 3; j++ ) + FOR( j = 0; j < 3; j++ ) { ( *pCombinedOrientationData )->Rmat_fx[sf_idx][i][j] = ( *pCombinedOrientationData )->Rmat_fx[0][i][j]; + move32(); } } } ( *pCombinedOrientationData )->shd_rot_max_order = -1; + move16(); } ivas_binRenderer_fx( hCldfbRend, pMultiBinPoseData, *pCombinedOrientationData, MAX_PARAM_SPATIAL_SUBFRAMES, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer_sfIn, Cldfb_ImagBuffer_sfIn, Q_in ); @@ -2148,12 +2153,12 @@ void ivas_rend_CldfbMultiBinRendProcess( { Copy32( &Cldfb_RealBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band ); Copy32( &Cldfb_ImagBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band ); - Scale_sig32( &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q6, *Q_in ) ); // Q6 - Scale_sig32( &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q6, *Q_in ) ); // Q6 + Scale_sig32( &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in_orig, *Q_in ) ); // Q_in_orig + Scale_sig32( &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in_orig, *Q_in ) ); // Q_in_orig } } } - *Q_in = Q6; + *Q_in = Q_in_orig; } return; diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 12ed81e07..4e568b5ab 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -413,31 +413,27 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( /* Update head positions */ IF( NE_16( pos_idx, 0 ) ) { + COMBINED_ORIENTATION_HANDLE pCombinedOrientationData = st_ivas->hCombinedOrientationData; + Word16 q_fact_orig; FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) { - IF( EQ_32( originalHeadRot[i].w_fx, -1610612736 /* -3.0f in Q29 */ ) ) - { - assert( 0 ); - } - else - { - st_ivas->hCombinedOrientationData->Quaternions[i].w = -12582912; // Q22 - move32(); - - Quat2EulerDegree( originalHeadRot[i], /* TODO tmu : fix bug with ordering*/ - &st_ivas->hCombinedOrientationData->Quaternions[i].z_fx, - &st_ivas->hCombinedOrientationData->Quaternions[i].y_fx, - &st_ivas->hCombinedOrientationData->Quaternions[i].x_fx ); - - st_ivas->hCombinedOrientationData->Quaternions[i].x_fx = L_add( st_ivas->hCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses[pos_idx][0] ); - st_ivas->hCombinedOrientationData->Quaternions[i].y_fx = L_add( st_ivas->hCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses[pos_idx][1] ); - st_ivas->hCombinedOrientationData->Quaternions[i].z_fx = L_add( st_ivas->hCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses[pos_idx][2] ); - move32(); - move32(); - move32(); - - Euler2Quat_fx( deg2rad_fx( st_ivas->hCombinedOrientationData->Quaternions[i].x_fx ), deg2rad_fx( st_ivas->hCombinedOrientationData->Quaternions[i].y_fx ), deg2rad_fx( st_ivas->hCombinedOrientationData->Quaternions[i].z_fx ), &st_ivas->hCombinedOrientationData->Quaternions[i] ); - } + pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22 + q_fact_orig = originalHeadRot[i].q_fact; + modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 ); + /*euler*/ + Quat2EulerDegree_fx( originalHeadRot[i], + &pCombinedOrientationData->Quaternions[i].z_fx, + &pCombinedOrientationData->Quaternions[i].y_fx, + &pCombinedOrientationData->Quaternions[i].x_fx ); + pCombinedOrientationData->Quaternions[i].x_fx = L_add( pCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + pCombinedOrientationData->Quaternions[i].y_fx = L_add( pCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + pCombinedOrientationData->Quaternions[i].z_fx = L_add( pCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + + Euler2Quat_fx( deg2rad_fx( pCombinedOrientationData->Quaternions[i].x_fx ), + deg2rad_fx( pCombinedOrientationData->Quaternions[i].y_fx ), + deg2rad_fx( pCombinedOrientationData->Quaternions[i].z_fx ), &pCombinedOrientationData->Quaternions[i] ); + + modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig ); } } @@ -472,7 +468,7 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( Word32 *p_tc[MAX_TRANSPORT_CHANNELS]; FOR( i = 0; i < st_ivas->nchan_transport; i++ ) { - p_tc[i] = st_ivas->hTcBuffer->tc[i] + st_ivas->hTcBuffer->n_samples_rendered; + p_tc[i] = st_ivas->hTcBuffer->tc_fx[i] + st_ivas->hTcBuffer->n_samples_rendered; } ivas_binaural_add_LFE_fx( st_ivas, nSamplesRendered, p_tc, p_bin_output ); } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 269806ccf..51fca0ec8 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -2048,7 +2048,8 @@ void ivas_rend_CldfbMultiBinRendProcess( Word32 Cldfb_Out_Real[MAX_HEAD_ROT_POSES*BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : Binaural signals */ Word32 Cldfb_Out_Imag[MAX_HEAD_ROT_POSES*BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const Word16 low_res_pre_rend_rot, - const Word16 num_subframes + const Word16 num_subframes, + Word16 *Q_in ); ivas_error ivas_rend_openCldfb( diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index c5156c2a5..604596496 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -259,7 +259,8 @@ static ivas_error renderSbaToMultiBinauralCldfb( Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const Word16 low_res_pre_rend_rot, - const Word16 num_subframes ); + const Word16 num_subframes, + const Word16 Q_in ); static ivas_error renderSbaToMultiBinaural( input_sba *sbaInput, @@ -359,6 +360,14 @@ static void convertBitsBufferToInternalBitsBuff( hBits->pose_correction = outBits.config.poseCorrection; hBits->codec_frame_size_ms = outBits.config.codec_frame_size_ms; + move16(); + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + return; } @@ -377,7 +386,7 @@ static void convertInternalBitsBuffToBitsBuffer( return; } -static void copyBufferToCLDFBarray( +static void copyBufferToCLDFBarray_fx( const IVAS_REND_AudioBuffer buffer, Word32 re[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 im[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] ) @@ -409,7 +418,7 @@ static void copyBufferToCLDFBarray( return; } -static void accumulateCLDFBArrayToBuffer( +static void accumulateCLDFBArrayToBuffer_fx( Word32 re[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 im[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], IVAS_REND_AudioBuffer *buffer ) @@ -4502,7 +4511,7 @@ ivas_error IVAS_REND_FeedInputAudio_fx( input_base *inputBase; Word16 numInputChannels; #ifdef SPLIT_REND_WITH_HEAD_ROT - Word16 cldfb2tdSampleFact; + Word16 cldfb2tdShift; #endif /* Validate function arguments */ @@ -4514,10 +4523,10 @@ ivas_error IVAS_REND_FeedInputAudio_fx( test(); #ifdef SPLIT_REND_WITH_HEAD_ROT - cldfb2tdSampleFact = ( inputAudio.config.is_cldfb ) ? 2 : 1; + cldfb2tdShift = ( inputAudio.config.is_cldfb ) ? 1 : 0; - if ( inputAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 0 ) || - ( ( MAX_BUFFER_LENGTH_PER_CHANNEL * cldfb2tdSampleFact ) < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 1 ) ) + IF( inputAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 0 ) || + ( ( shl( MAX_BUFFER_LENGTH_PER_CHANNEL, cldfb2tdShift ) ) < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 1 ) ) #else IF( inputAudio.config.numSamplesPerChannel <= 0 || LT_16( MAX_BUFFER_LENGTH_PER_CHANNEL, inputAudio.config.numSamplesPerChannel ) ) #endif @@ -4534,10 +4543,10 @@ ivas_error IVAS_REND_FeedInputAudio_fx( test(); move32(); // move added for typecasting #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && - hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && - hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && - ( inputAudio.config.numSamplesPerChannel * 1000 / cldfb2tdSampleFact ) != ( BINAURAL_RENDERING_FRAME_SIZE_MS * hIvasRend->num_subframes ) * hIvasRend->sampleRateOut ) + IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && + NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && + NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && + shr( i_mult( inputAudio.config.numSamplesPerChannel, 1000 ), cldfb2tdShift ) != i_mult( i_mult( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) #else IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && NE_32( L_mult0( inputAudio.config.numSamplesPerChannel, 1000 ), (Word32) W_mult0_32_32( L_mult0( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) ) @@ -4573,7 +4582,7 @@ ivas_error IVAS_REND_FeedInputAudio_fx( MVR2R_WORD32( inputAudio.data_fx, inputBase->inputBuffer.data_fx, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); #ifdef SPLIT_REND_WITH_HEAD_ROT - inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel / cldfb2tdSampleFact; + inputBase->numNewSamplesPerChannel = shr( inputAudio.config.numSamplesPerChannel, cldfb2tdShift ); #else inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel; #endif @@ -4852,27 +4861,27 @@ Word16 IVAS_REND_FeedRenderConfig( #ifdef SPLIT_REND_WITH_HEAD_ROT hRenderConfig->split_rend_config = renderConfig.split_rend_config; /* Overwrite any pose correction settings if 0 DOF (no pose correction) was selected */ - if ( hRenderConfig->split_rend_config.dof == 0 ) + IF( EQ_16( hRenderConfig->split_rend_config.dof, 0 ) ) { hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; } hRenderConfig->split_rend_config.codec = renderConfig.split_rend_config.codec; - if ( ( error = isar_split_rend_validate_config( &hRenderConfig->split_rend_config, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0 ) ) != IVAS_ERR_OK ) + IF( ( error = isar_split_rend_validate_config( &hRenderConfig->split_rend_config, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0 ) ) != IVAS_ERR_OK ) { return error; } /* Must re-initialize split rendering config in case renderer config is updated after adding renderer inputs */ /* if its not initialized yet then no need to re-initialize, initialization will happen while adding inputs*/ - if ( hIvasRend->splitRendEncBuffer.data_fx != NULL && hIvasRend->hRendererConfig != NULL ) + IF( hIvasRend->splitRendEncBuffer.data_fx != NULL && hIvasRend->hRendererConfig != NULL ) { int16_t cldfb_in_flag; cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); ISAR_PRE_REND_close( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer ); - if ( ( error = ivas_pre_rend_init( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_pre_rend_init( &hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK ) { return error; } @@ -5725,7 +5734,7 @@ static Word16 getNumSubframesInBuffer( const Word32 sampleRate ) { #ifdef SPLIT_REND_WITH_HEAD_ROT - int16_t cldfb2tdShift; + Word16 cldfb2tdShift; cldfb2tdShift = buffer->config.is_cldfb ? 1 : 0; @@ -5914,7 +5923,11 @@ static ivas_error renderIsmToBinauralRoom( } // Crend_process porting CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = ismInput->crendWrapper->hCrend[0]; +#else hCrend = ismInput->crendWrapper->hCrend; +#endif IF( hCrend->reflections != NULL ) { test(); @@ -6236,16 +6249,16 @@ static ivas_error renderIsmToSplitBinaural( const IVAS_REND_AudioBuffer outAudio ) { ivas_error error; - float tmpProcessing[MAX_NUM_OBJECTS][L_FRAME48k]; - int16_t pos_idx; + Word32 tmpProcessing[MAX_NUM_OBJECTS][L_FRAME48k]; + Word16 pos_idx; const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; const SPLIT_REND_WRAPPER *pSplitRendWrapper; IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t i; - float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; - int16_t output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; + Word16 i; + Word32 tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + Word16 output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; - int16_t ism_md_subframe_update_ext; + Word16 ism_md_subframe_update_ext; push_wmops( "renderIsmToSplitBinaural" ); @@ -6253,78 +6266,78 @@ static ivas_error renderIsmToSplitBinaural( pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */ - ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms_fx / ( 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + ism_md_subframe_update_ext = (Word16) Mpy_32_32( ismInput->ism_metadata_delay_ms_fx, ONE_BY_SUBFRAME_LEN_MS_Q31 ); pCombinedOrientationData = *ismInput->base.ctx.pCombinedOrientationData; - if ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) { - for ( i = 1; i < pCombinedOrientationData->num_subframes; ++i ) + FOR( i = 1; i < pCombinedOrientationData->num_subframes; ++i ) { - pCombinedOrientationData->Quaternions[i] = pCombinedOrientationData->Quaternions[0]; + Copy_Quat_fx( &pCombinedOrientationData->Quaternions[0], &pCombinedOrientationData->Quaternions[i] ); } } /* Save current head positions */ - for ( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) + FOR( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) { - originalHeadRot[i] = pCombinedOrientationData->Quaternions[i]; + Copy_Quat_fx( &pCombinedOrientationData->Quaternions[i], &originalHeadRot[i] ); } /* Copy input audio to a processing buffer. */ - copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing ); + copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing ); - for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { /* Update head positions */ - if ( pos_idx != 0 ) + IF( NE_16( pos_idx, 0 ) ) { - for ( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) + Word16 q_fact_orig; + FOR( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) { - if ( originalHeadRot[i].w == -3.0f ) - { - pCombinedOrientationData->Quaternions[i].w = -3.0f; - pCombinedOrientationData->Quaternions[i].x = originalHeadRot[i].x + pMultiBinPoseData->relative_head_poses[pos_idx][0]; - pCombinedOrientationData->Quaternions[i].y = originalHeadRot[i].y + pMultiBinPoseData->relative_head_poses[pos_idx][1]; - pCombinedOrientationData->Quaternions[i].z = originalHeadRot[i].z + pMultiBinPoseData->relative_head_poses[pos_idx][2]; - } - else - { - pCombinedOrientationData->Quaternions[i].w = -3.0f; - Quat2EulerDegree( originalHeadRot[i], - &pCombinedOrientationData->Quaternions[i].z, - &pCombinedOrientationData->Quaternions[i].y, - &pCombinedOrientationData->Quaternions[i].x ); - pCombinedOrientationData->Quaternions[i].x += pMultiBinPoseData->relative_head_poses[pos_idx][0]; - pCombinedOrientationData->Quaternions[i].y += pMultiBinPoseData->relative_head_poses[pos_idx][1]; - pCombinedOrientationData->Quaternions[i].z += pMultiBinPoseData->relative_head_poses[pos_idx][2]; - } + pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22 + q_fact_orig = originalHeadRot[i].q_fact; + modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 ); + /*euler*/ + Quat2EulerDegree_fx( originalHeadRot[i], + &pCombinedOrientationData->Quaternions[i].z_fx, + &pCombinedOrientationData->Quaternions[i].y_fx, + &pCombinedOrientationData->Quaternions[i].x_fx ); + pCombinedOrientationData->Quaternions[i].x_fx = L_add( pCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + pCombinedOrientationData->Quaternions[i].y_fx = L_add( pCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + pCombinedOrientationData->Quaternions[i].z_fx = L_add( pCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + + Euler2Quat_fx( deg2rad_fx( pCombinedOrientationData->Quaternions[i].x_fx ), + deg2rad_fx( pCombinedOrientationData->Quaternions[i].y_fx ), + deg2rad_fx( pCombinedOrientationData->Quaternions[i].z_fx ), &pCombinedOrientationData->Quaternions[i] ); + + modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig ); } } /* Render */ - if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[pos_idx - 1], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, - NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[sub( pos_idx, 1 )], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, + NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing ) ) != IVAS_ERR_OK ) { return error; } /* Copy rendered audio to tmp storage buffer. Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ - mvr2r( tmpProcessing[0], tmpBinaural[2 * pos_idx], output_frame ); - mvr2r( tmpProcessing[1], tmpBinaural[2 * pos_idx + 1], output_frame ); + Copy32( tmpProcessing[0], tmpBinaural[i_mult( 2, pos_idx )], output_frame ); + Copy32( tmpProcessing[1], tmpBinaural[add( i_mult( 2, pos_idx ), 1 )], output_frame ); /* Overwrite processing buffer with original input audio again */ - copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing ); + copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing ); } /* Restore original head rotation */ - for ( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) + FOR( i = 0; i < pCombinedOrientationData->num_subframes; ++i ) { - pCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; + Copy_Quat_fx( &originalHeadRot[i], &pCombinedOrientationData->Quaternions[i] ); } - accumulate2dArrayToBuffer( tmpBinaural, &outAudio ); + accumulate2dArrayToBuffer_fx( tmpBinaural, &outAudio ); pop_wmops(); /* Encoding to split rendering bitstream done at a higher level */ @@ -6517,6 +6530,7 @@ static ivas_error renderActiveInputsIsm( } return IVAS_ERR_OK; } + static ivas_error renderLfeToBinaural_fx( const input_mc *mcInput, #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -6528,7 +6542,7 @@ static ivas_error renderLfeToBinaural_fx( { Word16 lfe_idx; #ifdef SPLIT_REND_WITH_HEAD_ROT - int16_t pose_idx, num_poses; + Word16 pose_idx, num_poses; #endif Word32 gain_fx; Word16 ear_idx, i, r_shift; @@ -6595,20 +6609,22 @@ static ivas_error renderLfeToBinaural_fx( #ifdef SPLIT_REND_WITH_HEAD_ROT /* Copy LFE to left and right binaural channels for all poses */ - if ( mcInput->base.ctx.pSplitRendWrapper != NULL ) + IF( mcInput->base.ctx.pSplitRendWrapper != NULL ) { num_poses = mcInput->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses; + Move16(); } - else + ELSE { num_poses = 1; + move16(); } - for ( pose_idx = 0; pose_idx < num_poses; ++pose_idx ) + FOR( pose_idx = 0; pose_idx < num_poses; ++pose_idx ) { - for ( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx ) + FOR( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx ) { - writePtr = getSmplPtr_fx( outAudio, pose_idx * BINAURAL_CHANNELS + ear_idx, 0 ); + writePtr = getSmplPtr_fx( outAudio, add( i_mult( pose_idx, BINAURAL_CHANNELS ), ear_idx ), 0 ); v_add_fixed( writePtr, tmpLfeBuffer, writePtr, frame_size, 0 ); /* Q(out_q) */ } } @@ -6718,7 +6734,11 @@ static ivas_error renderMcToBinaural( } // Porting Crend_process function CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = mcInput->crendWrapper->hCrend[0]; +#else hCrend = mcInput->crendWrapper->hCrend; +#endif /* call CREND */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -6741,11 +6761,19 @@ static ivas_error renderMcToBinaural( accumulate2dArrayToBuffer_fx( tmpRendBuffer_fx, &outAudio ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) ) + + { + return error; + } +#else IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) ) { return error; } +#endif *outAudio.pq_fact = exp; move16(); pop_wmops(); @@ -6849,7 +6877,11 @@ static ivas_error renderMcToBinauralRoom( } // Porting Crend_process function CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = mcInput->crendWrapper->hCrend[0]; +#else hCrend = mcInput->crendWrapper->hCrend; +#endif /* call CREND */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -6976,7 +7008,11 @@ static ivas_error renderMcCustomLsToBinauralRoom( copyBufferTo2dArray_fx( tmpMcBuffer, tmpCrendBuffer ); CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = mcInput->crendWrapper->hCrend[0]; +#else hCrend = mcInput->crendWrapper->hCrend; +#endif /* call CREND */ #ifdef SPLIT_REND_WITH_HEAD_ROT IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, NULL, NULL, NULL, NULL, @@ -7072,45 +7108,61 @@ static ivas_error renderMcToSplitBinaural( const AUDIO_CONFIG outConfig, IVAS_REND_AudioBuffer outAudio ) { - int16_t i, j, pos_idx; - int16_t sf; - int16_t output_frame; + Word16 i, j, pos_idx; + Word16 sf; + Word16 output_frame; ivas_error error; const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; const SPLIT_REND_WRAPPER *pSplitRendWrapper; - float tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - float *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; - float tmpSplitBinauralBuffer[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + Word32 tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word32 *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS]; + Word32 tmpSplitBinauralBuffer[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; AUDIO_CONFIG inConfig; IVAS_REND_AudioBuffer tmpRotBuffer; COMBINED_ORIENTATION_DATA combinedOrientationDataLocal; COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal; + Word16 exp = *outAudio.pq_fact; + move16(); + CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = mcInput->crendWrapper->hCrend[0]; +#else + hCrend = mcInput->crendWrapper->hCrend; +#endif push_wmops( "renderMcToSplitBinaural" ); inConfig = mcInput->base.inConfig; + move32(); output_frame = mcInput->base.inputBuffer.config.numSamplesPerChannel; + move16(); pSplitRendWrapper = mcInput->base.ctx.pSplitRendWrapper; pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; + move32(); + move32(); - for ( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) { p_tmpRendBuffer[i] = tmpRendBuffer[i]; + move32(); } /* save current head positions */ pCombinedOrientationDataLocal = *mcInput->base.ctx.pCombinedOrientationData; + move32(); combinedOrientationDataLocal = *pCombinedOrientationDataLocal; - if ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + move32(); + IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) { - for ( sf = 1; sf < combinedOrientationDataLocal.num_subframes; ++sf ) + FOR( sf = 1; sf < combinedOrientationDataLocal.num_subframes; ++sf ) { - combinedOrientationDataLocal.Quaternions[sf] = combinedOrientationDataLocal.Quaternions[0]; - for ( i = 0; i < 3; i++ ) + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[0], &combinedOrientationDataLocal.Quaternions[sf] ); + FOR( i = 0; i < 3; i++ ) { - for ( j = 0; j < 3; j++ ) + FOR( j = 0; j < 3; j++ ) { - combinedOrientationDataLocal.Rmat[sf][i][j] = combinedOrientationDataLocal.Rmat[0][i][j]; + combinedOrientationDataLocal.Rmat_fx[sf][i][j] = combinedOrientationDataLocal.Rmat_fx[0][i][j]; + move32(); } } } @@ -7118,29 +7170,44 @@ static ivas_error renderMcToSplitBinaural( /* temporary buffer for rotation in source format for CREND */ tmpRotBuffer = mcInput->base.inputBuffer; - if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM && inConfig != IVAS_AUDIO_CONFIG_5_1 && inConfig != IVAS_AUDIO_CONFIG_7_1 ) + move32(); + IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) { - tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); } - for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { /* Update head positions */ IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; - for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + Word16 q_fact_orig; + FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) { - Quaternions_orig[i] = combinedOrientationDataLocal.Quaternions[i]; - Quaternions_abs.w = -3.0f; - Quat2EulerDegree( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/ + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] ); - Quaternions_abs.x += pMultiBinPoseData->relative_head_poses[pos_idx][0]; - Quaternions_abs.y += pMultiBinPoseData->relative_head_poses[pos_idx][1]; - Quaternions_abs.z += pMultiBinPoseData->relative_head_poses[pos_idx][2]; - combinedOrientationDataLocal.Quaternions[i] = Quaternions_abs; - QuatToRotMat( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat[i] ); + Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 + q_fact_orig = combinedOrientationDataLocal.Quaternions[i].q_fact; + modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 ); + /*euler*/ + Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], + &Quaternions_abs.z_fx, + &Quaternions_abs.y_fx, + &Quaternions_abs.x_fx ); + Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + + Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), + deg2rad_fx( Quaternions_abs.y_fx ), + deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs ); + + modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig ); + + Copy_Quat_fx( &Quaternions_abs, &combinedOrientationDataLocal.Quaternions[i] ); + QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); } - if ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM || inConfig == IVAS_AUDIO_CONFIG_5_1 || inConfig == IVAS_AUDIO_CONFIG_7_1 ) + IF( EQ_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) { /* tdrend processing overview: * 1. copy from inputBuffer to tmpRendBuffer @@ -7150,23 +7217,23 @@ static ivas_error renderMcToSplitBinaural( * 5. tmpSplitBinBuffer accumulated to outBuffer */ /* copy input to tdrend input/output buffer */ - copyBufferTo2dArray( mcInput->base.inputBuffer, tmpRendBuffer ); + copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer ); /* perform rotation in source format to tmpRotBuffer */ pCombinedOrientationDataLocal = &combinedOrientationDataLocal; /* Render */ - if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &mcInput->tdRendWrapper : &mcInput->splitTdRendWrappers[pos_idx - 1], mcInput->base.inConfig, &mcInput->customLsInput, &pCombinedOrientationDataLocal, NULL, mcInput->hReverb, 0, /* Ism Audio Metadata Delay Sync in ms for External Renderer */ *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &mcInput->tdRendWrapper : &mcInput->splitTdRendWrappers[pos_idx - 1], mcInput->base.inConfig, &mcInput->customLsInput, &pCombinedOrientationDataLocal, NULL, mcInput->hReverb, 0, /* Ism Audio Metadata Delay Sync in ms for External Renderer */ *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK ) { return error; } /* Copy rendered audio to tmp storage buffer. Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ - mvr2r( tmpRendBuffer[0], tmpSplitBinauralBuffer[2 * pos_idx], output_frame ); - mvr2r( tmpRendBuffer[1], tmpSplitBinauralBuffer[2 * pos_idx + 1], output_frame ); + Copy32( tmpRendBuffer[0], tmpSplitBinauralBuffer[i_mult( 2, pos_idx )], output_frame ); + Copy32( tmpRendBuffer[1], tmpSplitBinauralBuffer[add( i_mult( 2, pos_idx ), 1 )], output_frame ); } - else + ELSE { /* crend processing overview: * 1. rotateFrameMc: inputBuffer to tmpRotBuffer @@ -7177,49 +7244,60 @@ static ivas_error renderMcToSplitBinaural( /* copy input for in-place rotation */ - set_zero( tmpRotBuffer.data, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); + set32_fx( tmpRotBuffer.data_fx, 0, i_mult( tmpRotBuffer.config.numSamplesPerChannel, tmpRotBuffer.config.numChannels ) ); /* perform rotation in source format to tmpRotBuffer */ pCombinedOrientationDataLocal = &combinedOrientationDataLocal; - if ( ( error = rotateFrameMc( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, mcInput->rot_gains_prev[pos_idx], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) + IF( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, mcInput->rot_gains_prev_fx[pos_idx], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK ) { return error; } + IF( EQ_16( pos_idx, 0 ) ) + { + exp = sub( *outAudio.pq_fact, 1 ); + } - copyBufferTo2dArray( tmpRotBuffer, tmpRendBuffer ); + copyBufferTo2dArray_fx( tmpRotBuffer, tmpRendBuffer ); /* call CREND (rotation already performed) */ - if ( ( error = ivas_rend_crendProcessSubframe( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, - NULL, NULL, NULL, p_tmpRendBuffer, p_tmpRendBuffer, mcInput->base.inputBuffer.config.numSamplesPerChannel, *mcInput->base.ctx.pOutSampleRate, pos_idx ) ) != IVAS_ERR_OK ) + IF( NE_32( ( error = ivas_rend_crendProcess( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, + p_tmpRendBuffer, *mcInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &tmpRotBuffer, *mcInput->base.ctx.pOutSampleRate ), pos_idx ) ), + IVAS_ERR_OK ) ) + + IF( EQ_16( pos_idx, 0 ) ) { - return error; + IF( hCrend->hReverb != NULL ) + { + exp = sub( exp, 2 ); + } } /* Copy rendererd audio to tmp storage buffer, Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ - mvr2r( tmpRendBuffer[0], tmpSplitBinauralBuffer[2 * pos_idx], output_frame ); - mvr2r( tmpRendBuffer[1], tmpSplitBinauralBuffer[2 * pos_idx + 1], output_frame ); + Copy32( tmpRendBuffer[0], tmpSplitBinauralBuffer[i_mult( 2, pos_idx )], output_frame ); + Copy32( tmpRendBuffer[1], tmpSplitBinauralBuffer[add( i_mult( 2, pos_idx ), 1 )], output_frame ); } /* restore original headrotation data */ - for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) { - combinedOrientationDataLocal.Quaternions[i] = Quaternions_orig[i]; + Copy_Quat_fx( &Quaternions_orig[i], &combinedOrientationDataLocal.Quaternions[i] ); } } - if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM && inConfig != IVAS_AUDIO_CONFIG_5_1 && inConfig != IVAS_AUDIO_CONFIG_7_1 ) + IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) { /* free temporary buffer for rotation in source format for CREND */ - free( tmpRotBuffer.data ); + free( tmpRotBuffer.data_fx ); } - accumulate2dArrayToBuffer( tmpSplitBinauralBuffer, &outAudio ); + accumulate2dArrayToBuffer_fx( tmpSplitBinauralBuffer, &outAudio ); - if ( ( error = renderLfeToBinaural( mcInput, outConfig, outAudio ) ) != IVAS_ERR_OK ) + IF( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ) != IVAS_ERR_OK ) { return error; } + *outAudio.pq_fact = exp; pop_wmops(); return IVAS_ERR_OK; @@ -7364,97 +7442,113 @@ static void renderSbaToSba( static ivas_error renderSbaToMultiBinaural( input_sba *sbaInput, const AUDIO_CONFIG outConfig, - float out[][L_FRAME48k] ) + Word32 out[][L_FRAME48k] ) { - float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - float *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; - int16_t sf; - int16_t i, j, pos_idx; + Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word32 *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS]; + Word16 sf; + Word16 i, j, pos_idx; COMBINED_ORIENTATION_DATA combinedOrientationDataLocal; COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal; ivas_error error; IVAS_REND_AudioBuffer tmpRotBuffer; const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; - for ( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) { p_tmpCrendBuffer[i] = tmpCrendBuffer[i]; + move32(); } push_wmops( "renderSbaToMultiBinaural" ); pMultiBinPoseData = &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData; + move32(); pCombinedOrientationDataLocal = *sbaInput->base.ctx.pCombinedOrientationData; combinedOrientationDataLocal = *pCombinedOrientationDataLocal; - if ( pMultiBinPoseData->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + move32(); + move32(); + + IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ) { - for ( sf = 1; sf < combinedOrientationDataLocal.num_subframes; sf++ ) + FOR( sf = 1; sf < combinedOrientationDataLocal.num_subframes; ++sf ) { - combinedOrientationDataLocal.Quaternions[sf] = combinedOrientationDataLocal.Quaternions[0]; - for ( i = 0; i < 3; i++ ) + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[0], &combinedOrientationDataLocal.Quaternions[sf] ); + FOR( i = 0; i < 3; i++ ) { - for ( j = 0; j < 3; j++ ) + FOR( j = 0; j < 3; j++ ) { - combinedOrientationDataLocal.Rmat[sf][i][j] = combinedOrientationDataLocal.Rmat[0][i][j]; + combinedOrientationDataLocal.Rmat_fx[sf][i][j] = combinedOrientationDataLocal.Rmat_fx[0][i][j]; + move32(); } } } } tmpRotBuffer = sbaInput->base.inputBuffer; - tmpRotBuffer.data = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( float ) ); + tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); - for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; - for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + Word16 q_fact_orig; + FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) { - Quaternions_orig[i] = combinedOrientationDataLocal.Quaternions[i]; - Quaternions_abs.w = -3.0f; - Quat2EulerDegree( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/ + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] ); - Quaternions_abs.x += pMultiBinPoseData->relative_head_poses[pos_idx][0]; - Quaternions_abs.y += pMultiBinPoseData->relative_head_poses[pos_idx][1]; - Quaternions_abs.z += pMultiBinPoseData->relative_head_poses[pos_idx][2]; - combinedOrientationDataLocal.Quaternions[i] = Quaternions_abs; - QuatToRotMat( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat[i] ); - } + Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 + q_fact_orig = combinedOrientationDataLocal.Quaternions[i].q_fact; + modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 ); + /*euler*/ + Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], + &Quaternions_abs.z_fx, + &Quaternions_abs.y_fx, + &Quaternions_abs.x_fx ); + Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + + Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), + deg2rad_fx( Quaternions_abs.y_fx ), + deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs ); + modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig ); + + Copy_Quat_fx( &Quaternions_abs, &combinedOrientationDataLocal.Quaternions[i] ); + QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + } /* copy input for in-place rotation */ - mvr2r( sbaInput->base.inputBuffer.data, tmpRotBuffer.data, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); + Copy32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel ); pCombinedOrientationDataLocal = &combinedOrientationDataLocal; - if ( ( error = rotateFrameSba( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, sbaInput->rot_gains_prev[pos_idx], tmpRotBuffer ) ) != IVAS_ERR_OK ) + IF( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, sbaInput->rot_gains_prev_fx[pos_idx], tmpRotBuffer ) ) != IVAS_ERR_OK ) { return error; } - copyBufferTo2dArray( tmpRotBuffer, tmpCrendBuffer ); + copyBufferTo2dArray_fx( tmpRotBuffer, tmpCrendBuffer ); assert( sbaInput->crendWrapper->hCrend[0]->hReverb == NULL ); /* call CREND */ - if ( ( error = ivas_rend_crendProcessSubframe( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, - NULL, NULL, NULL, p_tmpCrendBuffer, p_tmpCrendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, *sbaInput->base.ctx.pOutSampleRate, pos_idx ) ) != IVAS_ERR_OK ) - { - return error; - } + IF( NE_32( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate, + getNumSubframesInBuffer( &tmpRotBuffer, *sbaInput->base.ctx.pOutSampleRate ), pos_idx ) ), + IVAS_ERR_OK ) ) - for ( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) { - combinedOrientationDataLocal.Quaternions[i] = Quaternions_orig[i]; + Copy_Quat_fx( &Quaternions_orig[i], &combinedOrientationDataLocal.Quaternions[i] ); } - /* move to output */ - for ( i = 0; i < BINAURAL_CHANNELS; i++ ) + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) { - mvr2r( tmpCrendBuffer[i], out[pos_idx * BINAURAL_CHANNELS + i], tmpRotBuffer.config.numSamplesPerChannel ); + Copy32( tmpCrendBuffer[i], out[pos_idx * BINAURAL_CHANNELS + i], tmpRotBuffer.config.numSamplesPerChannel ); } } - free( tmpRotBuffer.data ); + free( tmpRotBuffer.data_fx ); pop_wmops(); return IVAS_ERR_OK; @@ -7463,18 +7557,19 @@ static ivas_error renderSbaToMultiBinaural( static ivas_error renderSbaToMultiBinauralCldfb( input_sba *sbaInput, - float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - const int16_t low_res_pre_rend_rot, - const int16_t num_subframes ) + Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + const Word16 low_res_pre_rend_rot, + const Word16 num_subframes, + const Word16 Q_in ) { - float Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - copyBufferToCLDFBarray( sbaInput->base.inputBuffer, Cldfb_RealBuffer, Cldfb_ImagBuffer ); + copyBufferToCLDFBarray_fx( sbaInput->base.inputBuffer, Cldfb_RealBuffer, Cldfb_ImagBuffer ); ivas_rend_CldfbMultiBinRendProcess( sbaInput->cldfbRendWrapper.hCldfbRend, sbaInput->base.ctx.pCombinedOrientationData, &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData, - Cldfb_RealBuffer, Cldfb_ImagBuffer, Cldfb_Out_Real, Cldfb_Out_Imag, low_res_pre_rend_rot, num_subframes ); + Cldfb_RealBuffer, Cldfb_ImagBuffer, Cldfb_Out_Real, Cldfb_Out_Imag, low_res_pre_rend_rot, num_subframes, &Q_in ); return IVAS_ERR_OK; } @@ -7485,26 +7580,27 @@ static ivas_error renderSbaToSplitBinaural( const AUDIO_CONFIG outConfig, IVAS_REND_AudioBuffer outAudio ) { - float tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; ivas_error error; - float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - int16_t low_res_pre_rend_rot; + Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 low_res_pre_rend_rot; low_res_pre_rend_rot = 1; push_wmops( "renderSbaToSplitBinaural" ); error = IVAS_ERR_OK; + move32(); - if ( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + IF( EQ_32( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) ) { if ( ( renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, low_res_pre_rend_rot, - getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ) != IVAS_ERR_OK ) + getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ), *outAudio.pq_fact ) ) != IVAS_ERR_OK ) { return error; } - accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + accumulateCLDFBArrayToBuffer_fx( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); } else { @@ -7512,8 +7608,13 @@ static ivas_error renderSbaToSplitBinaural( { return error; } + IF( sbaInput->crendWrapper->hCrend[0]->hReverb != NULL ) + { + *outAudio.pq_fact = sub( *outAudio.pq_fact, Q2 ); + move16(); + } - accumulate2dArrayToBuffer( tmpCrendBuffer, &outAudio ); + accumulate2dArrayToBuffer_fx( tmpCrendBuffer, &outAudio ); } pop_wmops(); @@ -7538,26 +7639,27 @@ static ivas_error renderSbaToBinaural( push_wmops( "renderSbaToBinaural" ); #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) + IF( EQ_32( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) ) { - float Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - if ( ( error = renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, 0, - getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ) ) ) != IVAS_ERR_OK ) + IF( ( error = renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, 0, + getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ), *outAudio.pq_fact ) ) != IVAS_ERR_OK ) { return error; } - accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + accumulateCLDFBArrayToBuffer_fx( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); } - else + ELSE #endif { FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ ) { output_fx[i] = output_buffer_fx[i]; + move32(); } hCombinedOrientationData = sbaInput->base.ctx.pCombinedOrientationData; @@ -7611,7 +7713,11 @@ static ivas_error renderSbaToBinaural( } // Porting Crend_process function CREND_HANDLE hCrend; +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = sbaInput->crendWrapper->hCrend[0]; +#else hCrend = sbaInput->crendWrapper->hCrend; +#endif /* call CREND */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -7658,8 +7764,11 @@ static ivas_error renderSbaToBinauralRoom( push_wmops( "renderSbaToBinauralRoom" ); Word16 nchan_out; CREND_HANDLE hCrend; - +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = sbaInput->crendWrapper->hCrend[0]; +#else hCrend = sbaInput->crendWrapper->hCrend; +#endif IF( NE_32( ( error = getAudioConfigNumChannels( outConfig, &nchan_out ) ), IVAS_ERR_OK ) ) { @@ -7792,16 +7901,16 @@ static ivas_error renderInputSba( ivas_error error; IVAS_REND_AudioBuffer inAudio; #ifdef SPLIT_REND_WITH_HEAD_ROT - int16_t cldfb2tdSampleFact; + int16_t cldfb2tdShift; #endif error = IVAS_ERR_OK; move32(); inAudio = sbaInput->base.inputBuffer; #ifdef SPLIT_REND_WITH_HEAD_ROT - cldfb2tdSampleFact = outAudio.config.is_cldfb ? 2 : 1; - if ( ( sbaInput->base.numNewSamplesPerChannel * cldfb2tdSampleFact != outAudio.config.numSamplesPerChannel ) && - ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + cldfb2tdShift = outAudio.config.is_cldfb ? 1 : 0; + IF( NE_16( shl( sbaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) && + NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) #else IF( NE_32( sbaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) #endif @@ -8167,9 +8276,9 @@ static ivas_error renderInputMasa( Word32 *tmpBuffer_fx[MAX_OUTPUT_CHANNELS]; Word32 tmpBuffer_buff_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k]; #ifdef SPLIT_REND_WITH_HEAD_ROT - int16_t cldfb2tdSampleFact; - float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + int16_t cldfb2tdShift; + Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; #endif IF( !masaInput->metadataHasBeenFed ) @@ -8180,9 +8289,9 @@ static ivas_error renderInputMasa( inAudio = masaInput->base.inputBuffer; #ifdef SPLIT_REND_WITH_HEAD_ROT - cldfb2tdSampleFact = outAudio.config.is_cldfb ? 2 : 1; - if ( ( masaInput->base.numNewSamplesPerChannel * cldfb2tdSampleFact != outAudio.config.numSamplesPerChannel ) && - ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + cldfb2tdShift = outAudio.config.is_cldfb ? 1 : 0; + IF( ( NE_16( shl( masaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) ) && + NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) #else IF( NE_32( masaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) #endif @@ -8223,31 +8332,41 @@ static ivas_error renderInputMasa( num_subframes = shr( num_subframes, sub( 15, exp ) ); /* Q0 */ #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) { /* split rendering. use the combined of the first subframe in all subframes */ - int16_t sf, i, j; + Word16 sf, i, j; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; pCombinedOrientationData = *masaInput->base.ctx.pCombinedOrientationData; - for ( sf = 1; sf < pCombinedOrientationData->num_subframes; sf++ ) + FOR( sf = 1; sf < pCombinedOrientationData->num_subframes; sf++ ) { - pCombinedOrientationData->Quaternions[sf] = pCombinedOrientationData->Quaternions[0]; - for ( i = 0; i < 3; i++ ) + Copy_Quat_fx( &pCombinedOrientationData->Quaternions[0], &pCombinedOrientationData->Quaternions[sf] ); + FOR( i = 0; i < 3; i++ ) { - for ( j = 0; j < 3; j++ ) + FOR( j = 0; j < 3; j++ ) { - pCombinedOrientationData->Rmat[sf][i][j] = pCombinedOrientationData->Rmat[0][i][j]; + pCombinedOrientationData->Rmat_fx[sf][i][j] = pCombinedOrientationData->Rmat_fx[0][i][j]; + move32(); } } } - copyMasaMetadataToDiracRenderer( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); + copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin ); + Scale_sig32( tmpBuffer_buff_fx[0], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + Scale_sig32( tmpBuffer_buff_fx[1], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */ + + // scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) ); + - ivas_masa_ext_rend_parambin_render( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer, num_subframes, masaInput->base.ctx.pSplitRendWrapper, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); + ivas_masa_ext_rend_parambin_render_fx( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer_fx, num_subframes, masaInput->base.ctx.pSplitRendWrapper, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); - accumulateCLDFBArrayToBuffer( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + accumulateCLDFBArrayToBuffer_fx( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio ); + + + *outAudio.pq_fact = Q6; + move16(); } - else + ELSE { /* non-split path */ #endif @@ -8307,11 +8426,10 @@ static ivas_error renderInputMasa( default: return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) ); } + accumulate2dArrayToBuffer_fx( tmpBuffer_buff_fx, &outAudio ); #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif - - accumulate2dArrayToBuffer_fx( tmpBuffer_buff_fx, &outAudio ); } return IVAS_ERR_OK; @@ -8553,7 +8671,7 @@ static ivas_error getSamplesInternal( ivas_error error; Word16 numOutChannels; #ifdef SPLIT_REND_WITH_HEAD_ROT - int16_t cldfb2tdSampleFact; + int16_t cldfb2tdSampleShift; IVAS_REND_AudioBuffer outAudioOrig; #endif /* Validate function arguments */ @@ -8565,10 +8683,10 @@ static ivas_error getSamplesInternal( test(); #ifdef SPLIT_REND_WITH_HEAD_ROT - cldfb2tdSampleFact = ( outAudio.config.is_cldfb ) ? 2 : 1; + cldfb2tdSampleShift = ( outAudio.config.is_cldfb ) ? 1 : 0; - if ( outAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 0 ) || - ( ( MAX_BUFFER_LENGTH_PER_CHANNEL * cldfb2tdSampleFact ) < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 1 ) ) + IF( outAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 0 ) || + ( ( shl( MAX_BUFFER_LENGTH_PER_CHANNEL, cldfb2tdSampleShift ) ) < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 1 ) ) #else IF( outAudio.config.numSamplesPerChannel <= 0 || LT_16( MAX_BUFFER_LENGTH_PER_CHANNEL, outAudio.config.numSamplesPerChannel ) ) #endif @@ -8577,17 +8695,18 @@ static ivas_error getSamplesInternal( } test(); - IF( outAudio.config.numChannels <= 0 || LT_16( MAX_OUTPUT_CHANNELS, outAudio.config.numChannels ) ) + IF( LE_16( outAudio.config.numChannels, 0 ) || LT_16( MAX_OUTPUT_CHANNELS, outAudio.config.numChannels ) ) { return IVAS_ERR_WRONG_NUM_CHANNELS; } test(); #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( getAudioConfigType( hIvasRend->outputConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL && - hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && - hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && - ( outAudio.config.numSamplesPerChannel * 1000 / cldfb2tdSampleFact ) != ( hIvasRend->num_subframes * BINAURAL_RENDERING_FRAME_SIZE_MS ) * hIvasRend->sampleRateOut ) + IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && + NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && + NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && + NE_32( L_shr( L_mult0( outAudio.config.numSamplesPerChannel, 1000 ), cldfb2tdSampleShift ), + imult3216( hIvasRend->sampleRateOut, i_mult( hIvasRend->num_subframes, BINAURAL_RENDERING_FRAME_SIZE_MS ) ) ) ) #else IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && NE_32( L_mult0( outAudio.config.numSamplesPerChannel, 1000 ), imult3216( hIvasRend->sampleRateOut, i_mult( hIvasRend->num_subframes, BINAURAL_RENDERING_FRAME_SIZE_MS ) ) ) ) @@ -8671,7 +8790,7 @@ static ivas_error getSamplesInternal( } #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( numOutChannels != outAudio.config.numChannels && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( NE_16( numOutChannels, outAudio.config.numChannels ) && NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) #else IF( NE_16( numOutChannels, outAudio.config.numChannels ) ) #endif @@ -8685,26 +8804,20 @@ static ivas_error getSamplesInternal( #ifdef SPLIT_REND_WITH_HEAD_ROT outAudioOrig = outAudio; /* Use internal buffer if outputting split rendering bitstream */ - if ( ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || - ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || + EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - int16_t num_poses_orig; + Word16 num_poses_orig; num_poses_orig = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; + move16(); outAudio = hIvasRend->splitRendEncBuffer; - Word16 i, q_factor = Q22; ISAR_PRE_REND_GetMultiBinPoseData( &hIvasRend->hRendererConfig->split_rend_config, &hIvasRend->splitRendWrapper.multiBinPoseData, hIvasRend->headRotData.sr_pose_pred_axis ); - FOR( i = 0; i < MAX_HEAD_ROT_POSES; i++ ) - { - hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses[i][0] = fixedToFloat( hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses_fx[i][0], q_factor ); - hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses[i][1] = fixedToFloat( hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses_fx[i][1], q_factor ); - hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses[i][2] = fixedToFloat( hIvasRend->splitRendWrapper.multiBinPoseData.relative_head_poses_fx[i][2], q_factor ); - } assert( num_poses_orig == hIvasRend->splitRendWrapper.multiBinPoseData.num_poses && "number of poses should not change dynamically" ); /* Clear output buffer for split rendering bitstream */ - set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); + set32_fx( outAudio.data_fx, 0, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); } #endif @@ -8735,76 +8848,73 @@ static ivas_error getSamplesInternal( #endif #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { ISAR_SPLIT_REND_BITS_DATA bits; - int16_t cldfb_in_flag; - float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - for ( int i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + Word16 cldfb_in_flag, i, j, k, ch, ro_md_flag; + Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) { - for ( int j = 0; j < CLDFB_NO_COL_MAX; j++ ) + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - for ( int k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) + FOR( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) { Cldfb_RealBuffer_Binaural[i][j][k] = 0; Cldfb_ImagBuffer_Binaural[i][j][k] = 0; + move32(); + move32(); } } } - int16_t ch; - int16_t i, ro_md_flag; - float *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; - for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) + Word32 *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + + FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) { tmpBinaural[ch] = tmpBinaural_buff[ch]; + move32(); } - if ( outAudio.config.is_cldfb == 1 ) + IF( EQ_16( outAudio.config.is_cldfb, 1 ) ) { cldfb_in_flag = 1; - copyBufferToCLDFBarray( outAudio, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); + move16(); + copyBufferToCLDFBarray_fx( outAudio, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); } - else + ELSE { cldfb_in_flag = 0; - copyBufferTo2dArray( outAudio, tmpBinaural_buff ); + move16(); + copyBufferTo2dArray_fx( outAudio, tmpBinaural_buff ); } /* Encode split rendering bitstream */ convertBitsBufferToInternalBitsBuff( *hBits, &bits ); ro_md_flag = 0; - for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + move16(); + FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) { - if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + IF( NE_32( hIvasRend->inputsIsm[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) ) { ro_md_flag = 1; + move16(); break; } } - Word16 j; - Word16 q, q1 = 31, q2 = 31, Q_buff; - Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] = { 0 }; - Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] = { 0 }; - Word32 *pOutput_fx[CLDFB_NO_COL_MAX]; - Word32 output_fx[CLDFB_NO_COL_MAX][L_FRAME48k]; + + Word16 q1 = 31, q2 = 31, Q_buff; Word16 Q_out[CLDFB_NO_COL_MAX]; Q_out[0] = 31; - for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) - { - pOutput_fx[i] = &( output_fx[i][0] ); - } Word16 num_poses = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; + for ( i = 0; i < 16; i++ ) { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - q = Q_factor_arrL( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ); - q1 = s_min( q1, q ); - q = Q_factor_arrL( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ); - q2 = s_min( q2, q ); + q1 = s_min( q1, L_norm_arr( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) ); + q2 = s_min( q2, L_norm_arr( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) ); } } Q_buff = s_min( q1, q2 ); @@ -8812,96 +8922,55 @@ static ivas_error getSamplesInternal( { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - floatToFixed_arrL( Cldfb_RealBuffer_Binaural[i][j], Cldfb_RealBuffer_Binaural_fx[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); - floatToFixed_arrL( Cldfb_ImagBuffer_Binaural[i][j], Cldfb_ImagBuffer_Binaural_fx[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + scale_sig32( Cldfb_RealBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); } } + Q_buff = Q_buff + Q6; + IF( EQ_16( cldfb_in_flag, 0 ) ) { /*TD input*/ - /*if CLDFB handles have been allocated then assume valid multi binaural input in out[][] buffer and perform CLDFB analysis*/ - /* local float2fix, to be removed */ num_poses = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; - if ( hIvasRend->splitRendWrapper.hLc3plusEnc != NULL ) - { - Word16 frame_size_lc3 = (Word16) ( ( hIvasRend->splitRendWrapper.hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ) + hIvasRend->splitRendWrapper.lc3plusDelaySamples ); - FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) - { - Q_out[0] = s_min( Q_out[0], Q_factor_arrL( hIvasRend->splitRendWrapper.lc3plusDelayBuffers[i], frame_size_lc3 ) ); - } - } FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { - Q_out[0] = s_min( Q_out[0], Q_factor_arrL( tmpBinaural[i], L_FRAME48k ) ); + Q_out[0] = s_min( Q_out[0], L_norm_arr( tmpBinaural_buff[i], L_FRAME48k ) ); } - // printf("%d\n", Q_sig); - if ( hIvasRend->splitRendWrapper.hLc3plusEnc != NULL ) - { - Word16 frame_size_lc3 = (Word16) ( ( hIvasRend->splitRendWrapper.hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ) + hIvasRend->splitRendWrapper.lc3plusDelaySamples ); - FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) - { - floatToFixed_arrL( hIvasRend->splitRendWrapper.lc3plusDelayBuffers[i], hIvasRend->splitRendWrapper.lc3plusDelayBuffers_fx[i], Q_out[0], frame_size_lc3 ); - } - } FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { - floatToFixed_arrL( tmpBinaural[i], pOutput_fx[i], Q_out[0], L_FRAME48k ); + scale_sig32( tmpBinaural_buff[i], Q_out[0], L_FRAME48k ); } + + Q_out[0] = Q_out[0] + *outAudio.pq_fact; } + if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hIvasRend->splitRendWrapper, hIvasRend->headRotData.headPositions[0], hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, hIvasRend->hRendererConfig->split_rend_config.codec, #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms, #endif hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, - &bits, Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, pOutput_fx, 1, cldfb_in_flag, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, ro_md_flag, Q_buff, &Q_out[0] ) ) != IVAS_ERR_OK ) + &bits, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, 1, cldfb_in_flag, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, ro_md_flag, Q_buff, &Q_out[0] ) ) != IVAS_ERR_OK ) { return error; } - IF( EQ_16( cldfb_in_flag, 0 ) ) - { - if ( hIvasRend->splitRendWrapper.hLc3plusEnc != NULL ) - { - Word16 frame_size_lc3 = (Word16) ( ( hIvasRend->splitRendWrapper.hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ) + hIvasRend->splitRendWrapper.lc3plusDelaySamples ); - -#ifdef DUMP_LC3_DELAY_OUT - FILE *fp = fopen( "ref_lc3delay.txt", "ab" ); -#endif - FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) - { - fixedToFloat_arrL( hIvasRend->splitRendWrapper.lc3plusDelayBuffers_fx[i], hIvasRend->splitRendWrapper.lc3plusDelayBuffers[i], Q_out[0], frame_size_lc3 ); -#ifdef DUMP_LC3_DELAY_OUT - for ( Word16 j = 0; j < frame_size_lc3; j++ ) - { - fprintf( fp, "%f\n", hSplitBin->lc3plusDelayBuffers[i][j] ); - } -#endif - } -#ifdef DUMP_LC3_DELAY_OUT - fclose( fp ); -#endif - } - } Word16 pcm_out_flag = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0; - IF( NE_16( pcm_out_flag, 0 ) && ( NE_16( cldfb_in_flag, 0 ) ) ) + IF( NE_16( pcm_out_flag, 0 ) ) { - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + FOR( j = 0; j < BINAURAL_CHANNELS; j++ ) { - fixedToFloat_arrL( pOutput_fx[ch], tmpBinaural[ch], Q_out[ch], hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX ); - - fixedToFloat_arrL( hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->cldfb_state, hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->Q_split, hIvasRend->splitRendWrapper.hCldfbHandles->cldfbSyn[ch]->p_filter_length ); + scale_sig32( tmpBinaural_buff[j], L_FRAME48k, sub( *outAudio.pq_fact, Q_out[j] ) ); // *outAudio.pq_fact } } - convertInternalBitsBuffToBitsBuffer( hBits, bits ); /* reset to outAudioOrig in case of PCM output */ outAudio = outAudioOrig; - if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( NE_16( pcm_out_flag, 0 ) ) { accumulate2dArrayToBuffer( tmpBinaural_buff, &outAudio ); } -- GitLab From 86f8098b35ca91141446616aff0d1226a2be7ce5 Mon Sep 17 00:00:00 2001 From: rtyag Date: Tue, 4 Feb 2025 12:20:46 +1100 Subject: [PATCH 08/43] q factor fixes in renderer --- apps/isar_post_rend.c | 12 +- apps/renderer.c | 391 ++++++++++++++--------------- lib_isar/isar_splitRend_lcld_dec.c | 1 + lib_isar/isar_splitRendererPLC.c | 5 +- lib_isar/isar_splitRendererPost.c | 2 +- lib_isar/isar_splitRendererPre.c | 19 +- lib_isar/lib_isar_pre_rend.c | 10 +- lib_rend/lib_rend.c | 33 ++- lib_rend/lib_rend.h | 26 +- 9 files changed, 237 insertions(+), 262 deletions(-) diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c index 9a8d7c3ba..c28a5b811 100644 --- a/apps/isar_post_rend.c +++ b/apps/isar_post_rend.c @@ -952,12 +952,12 @@ int main( inBuffer.config.is_cldfb = 0; inBuffer.config.numChannels = (int16_t) totalNumInChannels; inBuffer.data_fx = inFloatBuffer_fx; - inBuffer.q_data_fx = malloc( sizeof( Word16 ) ); + inBuffer.pq_fact = malloc( sizeof( Word16 ) ); outBuffer.config.is_cldfb = 0; outBuffer.config.numChannels = (int16_t) numOutChannels; outBuffer.data_fx = outFloatBuffer_fx; - outBuffer.q_data_fx = malloc( sizeof( Word16 ) ); + outBuffer.pq_fact = malloc( sizeof( Word16 ) ); memset( outBuffer.data_fx, 0, outBuffer.config.numSamplesPerChannel * outBuffer.config.numChannels * sizeof( Word32 ) ); @@ -1035,7 +1035,7 @@ int main( /* Convert from int to float and from interleaved to packed */ convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer_fx ); - *inBuffer.q_data_fx = 0; + *inBuffer.pq_fact = 0; int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; @@ -1121,7 +1121,7 @@ int main( /* Convert from float to int and from packed to interleaved. * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ - convertOutputBuffer( outFloatBuffer_fx, *outBuffer.q_data_fx, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); + convertOutputBuffer( outFloatBuffer_fx, *outBuffer.pq_fact, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); if ( delayNumSamples == -1 ) { @@ -1225,10 +1225,10 @@ int main( /* === Close === */ free( inpInt16Buffer ); free( inFloatBuffer_fx ); - free( inBuffer.q_data_fx ); + free( inBuffer.pq_fact ); free( outInt16Buffer ); free( outFloatBuffer_fx ); - free( outBuffer.q_data_fx ); + free( outBuffer.pq_fact ); if ( bitsBufferData != NULL ) { diff --git a/apps/renderer.c b/apps/renderer.c index 9b64aff93..1979a7f1f 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -439,8 +439,36 @@ static IVAS_AUDIO_CONFIG parseAudioConfig( const char *configString ); static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna ); static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn ); -static void convertOutputBuffer_fx( const Word32 *Word32Buffer, const Word16 numSamplesPerChannel, const Word16 numChannels, Word16 *intBuffer, Word16 q_factor, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn ); -static void convertInputBuffer_fx( const Word16 *intBuffer, const Word16 numIntSamplesPerChannel, const Word16 numFloatSamplesPerChannel, const Word16 numChannels, Word32 *Int32Buffer, Word16 in_q_factor, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna ); +static void convertOutputBuffer_fx( + const Word32 *Word32Buffer, + const Word16 numSamplesPerChannel, + const Word16 numChannels, +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word16 *intBuffer, + const Word16 cldfb_in_flag, + IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn, + Word16 out_q +#else + Word16 *intBuffer, + Word16 out_q +#endif +); +static void convertInputBuffer_fx( + const Word16 *intBuffer, + const Word16 numIntSamplesPerChannel, + const Word16 numFloatSamplesPerChannel, + const Word16 numChannels, +#ifdef SPLIT_REND_WITH_HEAD_ROT + Word32 *Word32Buffer, + Word16 in_q_factor, + const int16_t cldfb_in_flag, + IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna, + Word16 *out_q_factor +#else + Word32 *Word32Buffer, + Word16 in_q_factor +#endif +); #else static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer ); @@ -1413,11 +1441,11 @@ int main( } #endif - if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) - { - fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); - exit( -1 ); - } + if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); + exit( -1 ); + } #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif @@ -1430,28 +1458,41 @@ int main( if ( cldfb_in_flag == 0 ) { inFloatBuffer = malloc( inBufferSize * sizeof( float ) ); - inBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); + outInt32Buffer = malloc( outBufferSize * sizeof( Word32 ) ); + inInt32Buffer = malloc( inBufferSize * sizeof( Word32 ) ); outFloatBuffer = malloc( outBufferSize * sizeof( float ) ); + + inBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + inBuffer.config.numChannels = (int16_t) totalNumInChannels; + outBuffer.config.numSamplesPerChannel = (int16_t) frameSize_smpls; + outBuffer.config.numChannels = (int16_t) numOutChannels; + outBuffer.data_fx = outInt32Buffer; + inBuffer.data_fx = inInt32Buffer; } else { inFloatBuffer = malloc( CLDFBframeSize_smpls * totalNumInChannels * sizeof( float ) ); - inBuffer.config.numSamplesPerChannel = (int16_t) CLDFBframeSize_smpls; + outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); + outInt32Buffer = malloc( CLDFBframeSize_smpls * totalNumInChannels * sizeof( Word32 ) ); + inInt32Buffer = malloc( CLDFBframeSize_smpls * totalNumInChannels * sizeof( Word32 ) ); outFloatBuffer = malloc( CLDFBframeSize_smpls * totalNumInChannels * sizeof( float ) ); + + inBuffer.config.numSamplesPerChannel = (int16_t) CLDFBframeSize_smpls; + inBuffer.config.numChannels = (int16_t) totalNumInChannels; + outBuffer.config.numSamplesPerChannel = (int16_t) CLDFBframeSize_smpls; + outBuffer.config.numChannels = (int16_t) numOutChannels; + outBuffer.data_fx = outInt32Buffer; + inBuffer.data_fx = inInt32Buffer; } - outInt16Buffer = malloc( outBufferSize * sizeof( int16_t ) ); inBuffer.config.is_cldfb = cldfb_in_flag; - inBuffer.config.numChannels = (int16_t) totalNumInChannels; - inBuffer.data = inFloatBuffer; - outBuffer.config.is_cldfb = cldfb_in_flag; - outBuffer.config.numChannels = (int16_t) numOutChannels; - outBuffer.data = outFloatBuffer; - memset( outBuffer.data, 0, outBuffer.config.numSamplesPerChannel * outBuffer.config.numChannels * sizeof( float ) ); + + memset( outBuffer.data_fx, 0, outBuffer.config.numSamplesPerChannel * outBuffer.config.numChannels * sizeof( Word32 ) ); if ( is_split_pre_rend_mode( &args ) ) { @@ -1533,12 +1574,15 @@ int main( /* Convert from int to float and from interleaved to packed */ #ifdef SPLIT_REND_WITH_HEAD_ROT - convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); + Word16 Q_out; + *outBuffer.pq_fact = 16 - ( gd_bits ); + convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, inBuffer.config.is_cldfb, cldfbAna, *outBuffer.pq_fact, &Q_out ); + *outBuffer.pq_fact = Q_out; #else - convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer ); -#endif *outBuffer.pq_fact = 16 - ( gd_bits ); convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, *outBuffer.pq_fact ); +#endif + int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; @@ -1764,15 +1808,15 @@ int main( else { #endif - if ( ( error = IVAS_REND_GetSamples( hIvasRend, outBuffer ) ) != IVAS_ERR_OK ) - { + if ( ( error = IVAS_REND_GetSamples( hIvasRend, outBuffer ) ) != IVAS_ERR_OK ) + { #ifdef SPLIT_REND_WITH_HEAD_ROT fprintf( stderr, "Error %s\n", ivas_error_to_string( error ) ); #else fprintf( stderr, "Error in getting samples\n" ); #endif - exit( -1 ); - } + exit( -1 ); + } #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif @@ -1782,18 +1826,12 @@ int main( /* Convert from float to int and from packed to interleaved. * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ - if ( *outBuffer.pq_fact == 0 ) - { - #ifdef SPLIT_REND_WITH_HEAD_ROT - convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, cldfb_in_flag, cldfbSyn ); +#ifdef SPLIT_REND_WITH_HEAD_ROT + convertOutputBuffer_fx( outInt32Buffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, cldfb_in_flag, cldfbSyn, *outBuffer.pq_fact ); #else - convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer ); + convertOutputBuffer_fx( outInt32Buffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, *outBuffer.pq_fact ); #endif - } - else - { - convertOutputBuffer_fx( outInt32Buffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, *outBuffer.pq_fact ); - } + if ( delayNumSamples == -1 ) { if ( args.delayCompensationEnabled ) @@ -1828,19 +1866,19 @@ int main( if ( audioWriter != NULL ) { #endif - if ( delayNumSamples * num_out_channels < outBufferSize ) - { - if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) + if ( delayNumSamples * num_out_channels < outBufferSize ) { - fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); - exit( -1 ); + if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); + exit( -1 ); + } + delayNumSamples = 0; + } + else + { + delayNumSamples -= (int16_t) ( outBufferSize / num_out_channels ); } - delayNumSamples = 0; - } - else - { - delayNumSamples -= (int16_t) ( outBufferSize / num_out_channels ); - } #ifdef SPLIT_REND_WITH_HEAD_ROT } @@ -1957,23 +1995,23 @@ int main( if ( audioWriter != NULL ) { #endif - for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) - { - memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) + for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) + { + memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + exit( -1 ); + } + } + + memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); + if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); exit( -1 ); } - } - - memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); - if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nOutput audio file writer error\n" ); - exit( -1 ); - } - zeroPadToWrite = 0; + zeroPadToWrite = 0; #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif @@ -3760,82 +3798,86 @@ static ivas_error parseLfePanMtxFile( * accepted by the renderer (float, packed) *--------------------------------------------------------------------------*/ -static void convertInputBuffer( - const int16_t *intBuffer, - const int16_t numIntSamplesPerChannel, - const int16_t numFloatSamplesPerChannel, - const int16_t numChannels, +static void convertInputBuffer_fx( + const Word16 *intBuffer, + const Word16 numIntSamplesPerChannel, + const Word16 numFloatSamplesPerChannel, + const Word16 numChannels, #ifdef SPLIT_REND_WITH_HEAD_ROT - float *floatBuffer, + Word32 *Word32Buffer, + Word16 in_q_factor, const int16_t cldfb_in_flag, - IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna + IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna, + Word16 *out_q_factor #else - float *floatBuffer + Word32 *Word32Buffer, + Word16 in_q_factor #endif ) { - int16_t chnl, smpl, i; + Word16 chnl, smpl, i; i = 0; #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( cldfb_in_flag ) + IF( cldfb_in_flag ) { - int16_t slotIdx, numCldfbBands, numFloatPcmSamples; - float fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; + Word16 slotIdx, numCldfbBands, numFloatPcmSamples; + Word32 fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; numFloatPcmSamples = numFloatSamplesPerChannel >> 1; numCldfbBands = numFloatPcmSamples / IVAS_CLDFB_NO_COL_MAX; /* CLDFB Analysis*/ assert( numIntSamplesPerChannel <= IVAS_MAX_OUTPUT_CHANNELS * IVAS_MAX_FRAME_SIZE ); - for ( smpl = 0; smpl < numFloatPcmSamples; ++smpl ) - { - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( smpl = 0; smpl < numFloatPcmSamples; ++smpl ) { - if ( i < numIntSamplesPerChannel ) - { - fIn[chnl][smpl] = (float) intBuffer[i]; - } - else + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - fIn[chnl][smpl] = 0.f; - } + IF( i < numIntSamplesPerChannel ) + { + fIn[chnl][smpl] = L_shl( (Word32) intBuffer[i], Q11 ); + } + ELSE + { + fIn[chnl][smpl] = 0; + } - ++i; + ++i; + } } - } - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - for ( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) + FOR( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) { IVAS_REND_cldfbAnalysis_ts_wrapper( &fIn[chnl][numCldfbBands * slotIdx], - &floatBuffer[( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], - &floatBuffer[numCldfbBands + ( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], - numCldfbBands, cldfbAna[chnl] ); + &Word32Buffer[( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], + &Word32Buffer[numCldfbBands + ( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], + numCldfbBands, cldfbAna[chnl], in_q_factor, *out_q_factor ); } } } - else + ELSE { #endif - for ( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) + FOR( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) { - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - if ( i < numIntSamplesPerChannel ) + IF( i < numIntSamplesPerChannel ) { - floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = (float) intBuffer[i]; + Word32Buffer[chnl * numFloatSamplesPerChannel + smpl] = L_shl( (Word32) intBuffer[i], in_q_factor ); } - else + ELSE { - floatBuffer[chnl * numFloatSamplesPerChannel + smpl] = 0.f; + Word32Buffer[chnl * numFloatSamplesPerChannel + smpl] = 0; } ++i; } } + *out_q_factor = in_q_factor; #ifdef SPLIT_REND_WITH_HEAD_ROT } #endif @@ -3843,174 +3885,105 @@ static void convertInputBuffer( return; } -/*--------------------------------------------------------------------------* - * convertInputBuffer() - * - * Convert input buffer from WAV/PCM file (int16_t, interleaved) to a format - * accepted by the renderer (float, packed) - *--------------------------------------------------------------------------*/ - -static void convertInputBuffer_fx( - const Word16 *intBuffer, - const Word16 numIntSamplesPerChannel, - const Word16 numFloatSamplesPerChannel, - const Word16 numChannels, - Word32 *Word32Buffer, - Word16 in_q_factor ) -{ - Word16 chnl, smpl, i; - - i = 0; - - FOR( smpl = 0; smpl < numFloatSamplesPerChannel; ++smpl ) - { - FOR( chnl = 0; chnl < numChannels; ++chnl ) - { - IF( i < numIntSamplesPerChannel ) - { - Word32Buffer[chnl * numFloatSamplesPerChannel + smpl] = L_shl( (Word32) intBuffer[i], in_q_factor ); - } - ELSE - { - Word32Buffer[chnl * numFloatSamplesPerChannel + smpl] = 0; - } - - ++i; - } - } - return; -} /*--------------------------------------------------------------------------* - * convertOutputBuffer() + * convertOutputBuffer_fx() * - * Convert output buffer from the renderer (Word32, packed) to a format ready - * for writing to a WAV/PCM file (Word16, interleaved) + * Convert output buffer from the renderer (float, packed) to a format ready + * for writing to a WAV/PCM file (int16_t, interleaved) *--------------------------------------------------------------------------*/ + static void convertOutputBuffer_fx( const Word32 *Word32Buffer, const Word16 numSamplesPerChannel, const Word16 numChannels, - Word16 *intBuffer, - Word16 out_q ) -{ - Word16 chnl, smpl, i; - Word32 temp_fx; - Word32 temp_fx1; - i = 0; - - FOR( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) - { - FOR( chnl = 0; chnl < numChannels; ++chnl ) - { - temp_fx = L_add( Word32Buffer[chnl * numSamplesPerChannel + smpl], lshl( 1, ( out_q - 1 ) ) ); - temp_fx1 = L_shr( temp_fx, out_q ); - IF( GT_32( temp_fx1, IVAS_MAX16B_FX ) ) - { - temp_fx1 = IVAS_MAX16B_FX; - } - ELSE IF( LT_32( temp_fx1, IVAS_MIN16B_FX ) ) - { - temp_fx1 = IVAS_MIN16B_FX; - } - intBuffer[i] = (Word16) temp_fx1; - - ++i; - } - } - - return; -} -/*--------------------------------------------------------------------------* - * convertOutputBuffer() - * - * Convert output buffer from the renderer (float, packed) to a format ready - * for writing to a WAV/PCM file (int16_t, interleaved) - *--------------------------------------------------------------------------*/ - -static void convertOutputBuffer( - const float *floatBuffer, - const int16_t numSamplesPerChannel, - const int16_t numChannels, #ifdef SPLIT_REND_WITH_HEAD_ROT - int16_t *intBuffer, - const int16_t cldfb_in_flag, - IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn + Word16 *intBuffer, + const Word16 cldfb_in_flag, + IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn, + Word16 out_q #else - int16_t *intBuffer + Word16 *intBuffer, + Word16 out_q #endif ) { - int16_t chnl, smpl, i; - float temp; - + Word16 chnl, smpl, i; + Word32 temp_fx; + Word32 temp_fx1; i = 0; #ifdef SPLIT_REND_WITH_HEAD_ROT - if ( cldfb_in_flag ) + IF( cldfb_in_flag ) { - int16_t slotIdx, numCldfbBands, numPcmSamples, b; - float fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; - float re[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; - float im[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; + Word16 slotIdx, numCldfbBands, numPcmSamples, b, temp_out_q; + Word32 fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; + Word32 re[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; + Word32 im[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; numPcmSamples = numSamplesPerChannel >> 1; numCldfbBands = numPcmSamples / IVAS_CLDFB_NO_COL_MAX; /* CLDFB Synthesis*/ - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - for ( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) + FOR( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) { - for ( b = 0; b < numCldfbBands; b++ ) + FOR( b = 0; b < numCldfbBands; b++ ) { - re[chnl][slotIdx][b] = floatBuffer[( chnl * numSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands ) + b]; - im[chnl][slotIdx][b] = floatBuffer[numCldfbBands + ( chnl * numSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands ) + b]; + re[chnl][slotIdx][b] = Word32Buffer[( chnl * numSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands ) + b]; + im[chnl][slotIdx][b] = Word32Buffer[numCldfbBands + ( chnl * numSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands ) + b]; + move32(); + move32(); } } } /* Implement CLDFB synthesis */ - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - float *RealBuffer[IVAS_CLDFB_NO_COL_MAX]; - float *ImagBuffer[IVAS_CLDFB_NO_COL_MAX]; + Word32 *RealBuffer[IVAS_CLDFB_NO_COL_MAX]; + Word32 *ImagBuffer[IVAS_CLDFB_NO_COL_MAX]; - for ( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) + FOR( slotIdx = 0; slotIdx < IVAS_CLDFB_NO_COL_MAX; slotIdx++ ) { RealBuffer[slotIdx] = re[chnl][slotIdx]; ImagBuffer[slotIdx] = im[chnl][slotIdx]; + move32(); + move32(); } - IVAS_REND_cldfbSynthesis_wrapper( RealBuffer, ImagBuffer, &( fIn[chnl][0] ), numCldfbBands * IVAS_CLDFB_NO_COL_MAX, cldfbSyn[chnl] ); + IVAS_REND_cldfbSynthesis_wrapper( RealBuffer, ImagBuffer, &( fIn[chnl][0] ), numCldfbBands * IVAS_CLDFB_NO_COL_MAX, cldfbSyn[chnl], out_q, &temp_out_q ); } - for ( smpl = 0; smpl < numPcmSamples; ++smpl ) + + FOR( smpl = 0; smpl < numPcmSamples; ++smpl ) { - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - intBuffer[i] = (int16_t) roundf( fIn[chnl][smpl] ); + intBuffer[i] = (Word16) L_shl( fIn[chnl][smpl], sub( out_q, temp_out_q ) ); ++i; } } } - else + ELSE { #endif - for ( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) + + FOR( smpl = 0; smpl < numSamplesPerChannel; ++smpl ) { - for ( chnl = 0; chnl < numChannels; ++chnl ) + FOR( chnl = 0; chnl < numChannels; ++chnl ) { - temp = floatBuffer[chnl * numSamplesPerChannel + smpl]; - temp = (float) floor( temp + 0.5f ); - if ( temp > IVAS_MAX16B_FLT ) + temp_fx = L_add( Word32Buffer[chnl * numSamplesPerChannel + smpl], lshl( 1, ( out_q - 1 ) ) ); + temp_fx1 = L_shr( temp_fx, out_q ); + IF( GT_32( temp_fx1, IVAS_MAX16B_FX ) ) { - temp = IVAS_MAX16B_FLT; + temp_fx1 = IVAS_MAX16B_FX; } - else if ( temp < IVAS_MIN16B_FLT ) + ELSE IF( LT_32( temp_fx1, IVAS_MIN16B_FX ) ) { - temp = IVAS_MIN16B_FLT; + temp_fx1 = IVAS_MIN16B_FX; } - intBuffer[i] = (int16_t) temp; + intBuffer[i] = (Word16) temp_fx1; ++i; } diff --git a/lib_isar/isar_splitRend_lcld_dec.c b/lib_isar/isar_splitRend_lcld_dec.c index 7e5c3e2bb..0d5ccae2f 100644 --- a/lib_isar/isar_splitRend_lcld_dec.c +++ b/lib_isar/isar_splitRend_lcld_dec.c @@ -36,6 +36,7 @@ #include "isar_prot.h" #include "ivas_prot.h" #include "prot.h" +#include "prot_fx.h" #include "control.h" #ifdef DEBUGGING #include "debug.h" diff --git a/lib_isar/isar_splitRendererPLC.c b/lib_isar/isar_splitRendererPLC.c index 152fe52f3..5d2f02af6 100644 --- a/lib_isar/isar_splitRendererPLC.c +++ b/lib_isar/isar_splitRendererPLC.c @@ -43,9 +43,8 @@ #include "debug.h" #endif #include "wmc_auto.h" -#include "prot_fx2.h" +#include "prot_fx.h" #include "basop_util.h" -#include "basop_mpy.h" #include "enh64.h" /*------------------------------------------------------------------------- @@ -1034,7 +1033,7 @@ ivas_error isar_splitBinRendPLCOpen( ISAR_SPLIT_REND_PLC_HANDLE hSplitRendPLC; error = IVAS_ERR_OK; - IF( ( hSplitRendPLC = (ISAR_SPLIT_REND_PLC_HANDLE) malloc( sizeof( SPLIT_REND_PLC_STRUCT ) ) ) == NULL ) + IF( ( hSplitRendPLC = (ISAR_SPLIT_REND_PLC_HANDLE) malloc( sizeof( ISAR_SPLIT_REND_PLC_STRUCT ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for bin split renderer PLC Module \n" ) ); } diff --git a/lib_isar/isar_splitRendererPost.c b/lib_isar/isar_splitRendererPost.c index 1bbff0b5c..840b102d0 100644 --- a/lib_isar/isar_splitRendererPost.c +++ b/lib_isar/isar_splitRendererPost.c @@ -44,7 +44,7 @@ #ifdef DEBUGGING #include "debug.h" #endif -#include "prot_fx2.h" +#include "prot_fx.h" #include "wmc_auto.h" #include "basop_util.h" #define Q31_BY_360 ( 5965232 ) // Q31 diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 2e2e19ac4..12e684767 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -49,7 +49,7 @@ #ifdef DBG_WAV_WRITER #include "string.h" #endif -#include "prot_fx2.h" +#include "prot_fx.h" #include "basop_util.h" /*---------------------------------------------------------------------* @@ -2909,7 +2909,6 @@ void isar_init_split_rend_handles( FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ++i ) { - hSplitRendWrapper->lc3plusDelayBuffers[i] = NULL; hSplitRendWrapper->lc3plusDelayBuffers_fx[i] = NULL; } hSplitRendWrapper->lc3plusDelaySamples = 0; @@ -2990,15 +2989,9 @@ ivas_error split_renderer_open_lc3plus( /* Alocate buffers for delay compensation */ IF( pSplitRendConfig->codec == ISAR_SPLIT_REND_CODEC_LC3PLUS ) { - delayBufferLength = (Word16) ( OutSampleRate / (int32_t) FRAMES_PER_SECOND + hSplitRendWrapper->lc3plusDelaySamples ); + delayBufferLength = (Word16) ( OutSampleRate / (int32_t) FRAMES_PER_SEC + hSplitRendWrapper->lc3plusDelaySamples ); FOR( i = 0; i < hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; ++i ) { - IF( ( hSplitRendWrapper->lc3plusDelayBuffers[i] = malloc( delayBufferLength * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); - } - - set_zero( hSplitRendWrapper->lc3plusDelayBuffers[i], delayBufferLength ); IF( ( hSplitRendWrapper->lc3plusDelayBuffers_fx[i] = malloc( delayBufferLength * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); @@ -3017,12 +3010,6 @@ ivas_error split_renderer_open_lc3plus( delayBufferLength = 2 /* Columns */ * 2 /* real and imag */ * CLDFB_NO_CHANNELS_MAX; FOR( i = 0; i < hSplitRendWrapper->multiBinPoseData.num_poses * BINAURAL_CHANNELS; ++i ) { - IF( ( hSplitRendWrapper->lc3plusDelayBuffers[i] = malloc( delayBufferLength * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); - } - - set_zero( hSplitRendWrapper->lc3plusDelayBuffers[i], delayBufferLength ); IF( ( hSplitRendWrapper->lc3plusDelayBuffers_fx[i] = malloc( delayBufferLength * sizeof( Word32 ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for multiBinPoseData handle\n" ) ); @@ -3165,7 +3152,7 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( /*this should always have the time resolution of pose correction MD. Note that this does not change frame size of LC3plus*/ // Word16 frame_size = (Word16) ( hSplitBin->hLc3plusEnc->config.samplerate / (Word32) FRAMES_PER_SECOND ); tmp_e = 0; - tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.samplerate, FRAMES_PER_SECOND_FX, &tmp_e ); + tmp = BASOP_Util_Divide3232_Scale( hSplitBin->hLc3plusEnc->config.samplerate, FRAMES_PER_SEC, &tmp_e ); Word16 frame_size = shr( tmp, sub( 15, tmp_e ) ); // Q0 FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 447fed0ba..44fe32f4a 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -36,6 +36,7 @@ #include #include "ivas_prot.h" #include "prot.h" +#include "prot_fx.h" #include "isar_cnst.h" #include "isar_rom_post_rend.h" #include "lib_isar_pre_rend.h" @@ -504,13 +505,12 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Q_cldfb = q_final; move16(); - Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split ) ); + Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state ) ); cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * num_slots, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1 Q_out[ch] = sub( Q_cldfb, 1 ); move16(); - hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split = Q_out[ch]; + hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state = Q_out[ch]; move16(); - fixedToFloat_arrL( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state, hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length ); } #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS @@ -561,11 +561,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Q_cldfb = q_final; move16(); - Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split ) ); + Scale_sig32( hSplitBin->hCldfbHandles->cldfbSyn[ch]->cldfb_state_fx, hSplitBin->hCldfbHandles->cldfbSyn[ch]->p_filter_length, sub( sub( Q_cldfb, 1 ), hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state ) ); cldfbSynthesis_ivas_fx( Cldfb_In_BinReal_p_fx, Cldfb_In_BinImag_p_fx, pOutput_fx[ch], hSplitBin->hCldfbHandles->cldfbSyn[0]->no_channels * CLDFB_NO_COL_MAX, hSplitBin->hCldfbHandles->cldfbSyn[ch] ); // Q_cldfb - 1 Q_out[ch] = sub( Q_cldfb, 1 ); move16(); - hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_split = Q_out[ch]; + hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state = Q_out[ch]; move16(); } diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 604596496..b33ce2942 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -9226,11 +9226,17 @@ void IVAS_REND_cldfbAnalysis_ts_wrapper( float realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ float imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ const int16_t samplesToProcess, /* i : samples to process */ - IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filterbank state */ -) + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filterbank state */ + Word16 Q_in, + Word16 *Q_out ) { cldfbAnalysis_ts( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb ); + Word16 Q_cldfb = Q_in; + cldfbAnalysis_ts_fx_fixed_q( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb, + &Q_cldfb ); + *Q_out = sub( Q_in, 5 ); + return; } @@ -9242,14 +9248,21 @@ void IVAS_REND_cldfbAnalysis_ts_wrapper( *-------------------------------------------------------------------*/ void IVAS_REND_cldfbSynthesis_wrapper( - float **realBuffer, /* i : real values */ - float **imagBuffer, /* i : imag values */ - float *timeOut, /* o : output time domain samples */ - const int16_t samplesToProcess, /* i : number of processed samples */ - IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filter bank state */ -) -{ - cldfbSynthesis( realBuffer, imagBuffer, timeOut, samplesToProcess, h_cldfb ); + Word32 **realBuffer, /* i : real values */ + Word32 **imagBuffer, /* i : imag values */ + Word32 *timeOut, /* o : output time domain samples */ + const int16_t samplesToProcess, /* i : number of processed samples */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filter bank state */ + Word16 Q_cldfb, + Word16 Q_out ) +{ + + Scale_sig32( h_cldfb->cldfb_state_fx, h_cldfb->p_filter_length, sub( sub( Q_cldfb, 1 ), h_cldfb->Q_cldfb_state ) ); + cldfbSynthesis_ivas_fx( realBuffer, imagBuffer, timeOut, samplesToProcess, h_cldfb ); // Q_cldfb - 1 + Q_out = sub( Q_cldfb, 1 ); + move16(); + h_cldfb->Q_cldfb_state = Q_out; + move16(); return; } diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 60d217bad..59f0ea4dd 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -386,20 +386,22 @@ void IVAS_REND_closeCldfb( ); void IVAS_REND_cldfbAnalysis_ts_wrapper( - const Word32 *timeIn, /* i : time buffer */ - Word32 realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ - Word32 imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ - const Word16 samplesToProcess, /* i : samples to process */ - IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filterbank state */ -); + const float *timeIn, /* i : time buffer */ + float realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ + float imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ + const int16_t samplesToProcess, /* i : samples to process */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filterbank state */ + Word16 Q_in, + Word16 *Q_out ); void IVAS_REND_cldfbSynthesis_wrapper( - Word32 **realBuffer, /* i : real values */ - Word32 **imagBuffer, /* i : imag values */ - Word32 *timeOut, /* o : output time domain samples */ - const Word16 samplesToProcess, /* i : number of processed samples */ - IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb /* i : filter bank state */ -); + Word32 **realBuffer, /* i : real values */ + Word32 **imagBuffer, /* i : imag values */ + Word32 *timeOut, /* o : output time domain samples */ + const int16_t samplesToProcess, /* i : number of processed samples */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filter bank state */ + Word16 Q_cldfb, + Word16 Q_out ); #endif -- GitLab From eabcb20b922ac7307c644ef6baf39f9c42077f2c Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 01:41:31 +1100 Subject: [PATCH 09/43] co[pilation fixes on windows --- Workspace_msvc/lib_isar.vcxproj | 32 ++----- Workspace_msvc/lib_lc3plus.vcxproj | 4 +- apps/decoder.c | 47 ++++------ apps/renderer.c | 2 +- lib_com/cnst.h | 5 ++ lib_com/delay_comp.c | 2 +- lib_com/enh1632.c | 21 +++++ lib_com/enh1632.h | 1 + lib_com/ivas_prot_fx.h | 12 --- lib_com/ivas_rotation_com.c | 70 +-------------- lib_com/prot_fx.h | 2 +- lib_com/tools_fx.c | 20 ----- lib_com/typedef.h | 2 + lib_dec/ivas_binRenderer_internal.c | 33 ++++--- lib_dec/ivas_dirac_dec.c | 16 ++-- lib_dec/ivas_init_dec.c | 16 ++-- lib_dec/ivas_init_dec_fx.c | 4 + lib_dec/ivas_ism_dec.c | 12 +-- lib_dec/ivas_ism_param_dec.c | 21 ++--- lib_dec/ivas_jbm_dec.c | 21 +++-- lib_dec/ivas_masa_dec.c | 2 +- lib_dec/ivas_mc_param_dec.c | 16 +++- lib_dec/ivas_mc_paramupmix_dec.c | 25 ++++-- lib_dec/ivas_mct_dec.c | 6 +- lib_dec/ivas_omasa_dec.c | 2 +- lib_dec/ivas_osba_dec.c | 15 ++-- lib_dec/ivas_output_config.c | 43 +++++---- lib_dec/ivas_sba_dec.c | 18 ++-- lib_dec/ivas_spar_decoder.c | 9 +- lib_dec/lib_dec_fx.c | 10 ++- lib_isar/isar_PredDecoder.c | 1 - lib_isar/isar_PredEncoder.c | 2 +- lib_isar/isar_RMSEnvGrouping.c | 2 +- lib_isar/isar_lcld_decoder.c | 2 +- lib_isar/isar_lcld_encoder.c | 3 +- lib_isar/isar_prot.h | 15 ++-- lib_isar/isar_splitRendererPLC.c | 18 ---- lib_isar/isar_splitRendererPost.c | 9 +- lib_isar/isar_splitRendererPre.c | 7 +- lib_isar/isar_splitRenderer_utils.c | 67 +------------- lib_isar/lib_isar_post_rend.c | 18 ++-- lib_isar/lib_isar_pre_rend.c | 8 +- lib_lc3plus/apply_global_gain_fx.c | 2 +- lib_lc3plus/ari_codec.c | 16 ++-- lib_lc3plus/basop_util_lc3plus.c | 2 +- lib_lc3plus/basop_util_lc3plus.h | 2 +- lib_lc3plus/cutoff_bandwidth.c | 2 +- lib_lc3plus/dct4_fx.c | 2 +- lib_lc3plus/dec_entropy.c | 2 +- lib_lc3plus/ltpf_coder_fx.c | 4 +- lib_lc3plus/olpa_fx.c | 4 +- lib_lc3plus/plc_xcorr_fx.c | 2 +- lib_rend/ivas_crend.c | 12 +-- lib_rend/ivas_dirac_dec_binaural_functions.c | 22 +++-- lib_rend/ivas_orient_trk.c | 10 +++ lib_rend/ivas_output_init.c | 6 +- lib_rend/ivas_prot_rend.h | 10 +-- lib_rend/ivas_reflections.c | 16 +++- lib_rend/ivas_rotation.c | 14 +-- lib_rend/lib_rend.c | 93 +++++++++++++++----- lib_rend/lib_rend.h | 10 +-- lib_util/rotation_file_reader.c | 25 +++++- 62 files changed, 416 insertions(+), 481 deletions(-) diff --git a/Workspace_msvc/lib_isar.vcxproj b/Workspace_msvc/lib_isar.vcxproj index c663ef5e7..23d803730 100644 --- a/Workspace_msvc/lib_isar.vcxproj +++ b/Workspace_msvc/lib_isar.vcxproj @@ -13,16 +13,16 @@ lib_isar {869A305E-D99E-4C3A-BDB3-AA57ABCCE619} - evs_dec + isar 10.0.17763.0 + StaticLibrary v141 false MultiByte - StaticLibrary v141 @@ -47,33 +47,24 @@ .\Debug_$(ProjectName)\ .\Debug_$(ProjectName)\ - false - false - libivasrend + libisar .\Release_$(ProjectName)\ .\Release_$(ProjectName)\ - false - false - libivasrend + libisar - - .\Debug\$(ProjectName).tlb - - Disabled - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_lc3plus;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_lc3plus;.%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions); EnableFastChecks MultiThreadedDebug - false $(IntDir)$(ProjectName).pdb @@ -82,7 +73,6 @@ OldStyle Default %(DisableSpecificWarnings) - false _DEBUG;%(PreprocessorDefinitions) @@ -98,10 +88,6 @@ - - $(IntDir)$(ProjectName).tlb - - MaxSpeed AnySuitable @@ -109,14 +95,13 @@ Neither false false - ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_lc3plus;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;..\lib_dec;..\lib_enc;..\lib_rend;..\lib_isar;..\lib_lc3plus;.%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;$(Macros);WIN32;%(PreprocessorDefinitions) true Default MultiThreaded true - false $(IntDir)$(ProjectName).pdb @@ -125,7 +110,6 @@ Default %(DisableSpecificWarnings) - false NDEBUG;%(PreprocessorDefinitions) @@ -138,7 +122,6 @@ - @@ -163,7 +146,6 @@ - diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index 294677fff..b22697021 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -65,7 +65,7 @@ Level3 - ..\lib_com;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) Disabled MultiThreadedDebug WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) @@ -84,7 +84,7 @@ Level3 - ..\lib_com;%(AdditionalIncludeDirectories) + ..\lib_com;..\lib_debug;%(AdditionalIncludeDirectories) MaxSpeed MultiThreaded true diff --git a/apps/decoder.c b/apps/decoder.c index 77126067e..6ad1ebd6a 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -1942,13 +1942,15 @@ static ivas_error decodeG192( { for ( i = 0; i < num_subframes; i++ ) { - Quaternions[i].w = -3.0f; - Quaternions[i].x = 0.0f; - Quaternions[i].y = 0.0f; - Quaternions[i].z = 0.0f; - Pos[i].x = 0.0f; - Pos[i].y = 0.0f; - Pos[i].z = 0.0f; + Quaternions[i].w_fx = -12582912; + Quaternions[i].x_fx = 0; + Quaternions[i].y_fx = 0; + Quaternions[i].z_fx = 0; + Quaternions[i].q_fact = 22; + Pos[i].x_fx = 0; + Pos[i].y_fx = 0; + Pos[i].z_fx = 0; + Pos[i].q_fact = 25; } } else @@ -2046,13 +2048,7 @@ static ivas_error decodeG192( else { #endif -#ifdef SPLIT_REND_WITH_HEAD_ROT - if ( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, IVAS_DEC_PCM_INT16, (void *) ( pcmBuf + nOutChannels * nSamplesRendered ), &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) - -#else - if ( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, ( pcmBuf + nOutChannels * nSamplesRendered ), &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) - -#endif + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, nSamplesToRender, ( pcmBuf + nOutChannels * nSamplesRendered ), &nSamplesRendered_loop, &needNewFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -2264,11 +2260,7 @@ static ivas_error decodeG192( } /* decode and get samples */ -#ifdef SPLIT_REND_WITH_HEAD_ROT - if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) -#else if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) -#endif { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -2655,13 +2647,15 @@ static ivas_error decodeVoIP( { for ( i = 0; i < num_subframes; i++ ) { - Quaternions[i].w = -3.0f; - Quaternions[i].x = 0.0f; - Quaternions[i].y = 0.0f; - Quaternions[i].z = 0.0f; + Quaternions[i].w_fx = -12582912; + Quaternions[i].x_fx = 0; + Quaternions[i].y_fx = 0; + Quaternions[i].z_fx = 0; + Quaternions[i].q_fact = 22; Pos[i].x = 0.0f; Pos[i].y = 0.0f; Pos[i].z = 0.0f; + Pos[i].q_fact = 25; } } else @@ -2774,19 +2768,10 @@ static ivas_error decodeVoIP( /* decode and get samples */ - -#ifdef SPLIT_REND_WITH_HEAD_ROT -#ifdef SUPPORT_JBM_TRACEFILE - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, systemTime_ms, writeJbmTraceFileFrameWrapper, jbmTraceWriter ) ) != IVAS_ERR_OK ) -#else - if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) -#endif -#else #ifdef SUPPORT_JBM_TRACEFILE if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms, writeJbmTraceFileFrameWrapper, jbmTraceWriter ) ) != IVAS_ERR_OK ) #else if ( ( error = IVAS_DEC_VoIP_GetSamples( hIvasDec, nOutSamples, pcmBuf, systemTime_ms ) ) != IVAS_ERR_OK ) -#endif #endif { fprintf( stderr, "\nError in IVAS_DEC_VoIP_GetSamples: %s\n", IVAS_DEC_GetErrorMessage( error ) ); diff --git a/apps/renderer.c b/apps/renderer.c index 1979a7f1f..09b1425ce 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -3854,7 +3854,7 @@ static void convertInputBuffer_fx( IVAS_REND_cldfbAnalysis_ts_wrapper( &fIn[chnl][numCldfbBands * slotIdx], &Word32Buffer[( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], &Word32Buffer[numCldfbBands + ( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], - numCldfbBands, cldfbAna[chnl], in_q_factor, *out_q_factor ); + numCldfbBands, cldfbAna[chnl], Q11, *out_q_factor ); } } } diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 35dc4f02a..e7c601ca3 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -3069,8 +3069,13 @@ enum #define SYNC_BAD_FRAME (UWord16) 0x6B20 /* synchronization word of a "bad" frame */ #define G192_BIN0 (UWord16) 0x007F /* binary "0" according to ITU-T G.192 */ #define G192_BIN1 (UWord16) 0x0081 /* binary "1" according to ITU-T G.192 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT +#define DEGREE_180 (Word32)(180.0 *ONE_IN_Q22) +#define DEGREE_360 (Word32)(360.0 *ONE_IN_Q22) +#else #define DEGREE_180 (Word32)(180.0 *ONE_IN_Q23) #define DEGREE_360 (Word32)(360.0 *ONE_IN_Q23) +#endif extern const Word16 Idx2Freq_Tbl[]; #define chk_fs(fs) diff --git a/lib_com/delay_comp.c b/lib_com/delay_comp.c index 38a077f9e..581db32bd 100644 --- a/lib_com/delay_comp.c +++ b/lib_com/delay_comp.c @@ -110,7 +110,7 @@ Word32 get_delay_fx( /* o : delay value in ms #ifdef SPLIT_REND_WITH_HEAD_ROT - IF( NE_16( output_config, AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) + IF( NE_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ) { #endif if ( hCldfb != NULL ) diff --git a/lib_com/enh1632.c b/lib_com/enh1632.c index bac18231e..f397c3432 100644 --- a/lib_com/enh1632.c +++ b/lib_com/enh1632.c @@ -616,6 +616,27 @@ Word32 L_rotr( Word32 L_var1, Word16 var2, Word16 *var3 ) } +int16_t norm_ul( uint32_t UL_var1 ) +{ + int16_t var_out; + + if ( UL_var1 == 0 ) + { + var_out = 0; + } + else + { + for ( var_out = 0; UL_var1 < (uint32_t) 0x80000000U; var_out++ ) + { + UL_var1 <<= 1; + } + } + BASOP_CHECK(); + + return ( var_out ); +} + + /***************************************************************************** * * Function Name : L_rotl diff --git a/lib_com/enh1632.h b/lib_com/enh1632.h index 10c10866a..f91494fb1 100644 --- a/lib_com/enh1632.h +++ b/lib_com/enh1632.h @@ -55,6 +55,7 @@ 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 ); +Word16 norm_ul( UWord32 UL_var1 ); /***************************************************************************** * diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 0fd85daae..9429640ba 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -5907,12 +5907,6 @@ void reset_metadata_spatial_fx( const Word16 nb_bits_metadata /* i : number of meatdata bits */ ); -void Euler2Quat( - const float yaw, /* i : yaw (x) */ - const float pitch, /* i : pitch (y) */ - const float roll, /* i : roll (z) */ - IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ -); void Euler2Quat_fx( const Word32 yaw, /* i : yaw (x) Q22 */ const Word32 pitch, /* i : pitch (y) Q22 */ @@ -5926,12 +5920,6 @@ Word32 deg2rad_fx( Word32 degrees ); #ifdef SPLIT_REND_WITH_HEAD_ROT -void Quat2EulerDegree( - const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ -); void Quat2EulerDegree_fx( const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ Word32 *yaw_fx, /* o : yaw */ diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index fc390dfb2..8aae50841 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -76,26 +76,6 @@ void Euler2Quat_fx( return; } -void Euler2Quat( - const float yaw, /* i : yaw (x) */ - const float pitch, /* i : pitch (y) */ - const float roll, /* i : roll (z) */ - IVAS_QUATERNION *quat /* o : quaternion describing the rotation */ -) -{ - float cr = cosf( roll * 0.5f ); - float sr = sinf( roll * 0.5f ); - float cp = cosf( pitch * 0.5f ); - float sp = sinf( pitch * 0.5f ); - float cy = cosf( yaw * 0.5f ); - float sy = sinf( yaw * 0.5f ); - quat->w = cr * cp * cy + sr * sp * sy; - quat->x = sr * cp * cy - cr * sp * sy; - quat->y = sr * cp * sy + cr * sp * cy; - quat->z = cr * cp * sy - sr * sp * cy; - - return; -} #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -258,61 +238,15 @@ void Quat2EulerDegree_fx( return; } -void Quat2EulerDegree( - const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ -) -{ - if ( quat.w != -3.0 ) - { - float p; - - *yaw = atan2f( 2 * ( quat.w * quat.x + quat.y * quat.z ), 1 - 2 * ( quat.x * quat.x + quat.y * quat.y ) ); - - p = 2 * ( quat.w * quat.y - quat.z * quat.x ); - p = max( -1.0f, min( 1.0f, p ) ); - *pitch = asinf( p ); - - *roll = atan2f( 2 * ( quat.w * quat.z + quat.x * quat.y ), 1 - 2 * ( quat.y * quat.y + quat.z * quat.z ) ); - - *yaw *= _180_OVER_PI; - *pitch *= _180_OVER_PI; - *roll *= _180_OVER_PI; - } - else - { - /* Euler angles in R_X(roll)*R_Y(pitch)*R_Z(yaw) convention - * - * yaw: rotate scene counter-clockwise in the horizontal plane - * pitch: rotate scene in the median plane, increase elevation with positive values - * roll: rotate scene from the right ear to the top - */ - *yaw = quat.z; - *pitch = quat.y; - *roll = quat.x; - } - - return; -} #endif -/*------------------------------------------------------------------------- - * deg2rad() - * - * Converts degrees to normalized radians - *------------------------------------------------------------------------*/ -#define DEGREE_180 ( Word32 )( 180.0 * ONE_IN_Q22 ) -#define DEGREE_360 ( Word32 )( 360.0 * ONE_IN_Q22 ) -#define PI_OVER_180_FX ( Word32 )( ( EVS_PI / 180.0f ) * ONE_IN_Q31 ) /*------------------------------------------------------------------------- * deg2rad() * * Converts degrees to normalized radians *------------------------------------------------------------------------*/ Word32 deg2rad_fx( - Word32 degrees // Q23 + Word32 degrees // Q22 ) { WHILE( GE_32( degrees, DEGREE_180 ) ) @@ -324,7 +258,7 @@ Word32 deg2rad_fx( degrees = L_add( degrees, DEGREE_360 ); } - return Mpy_32_32( PI_OVER_180_FX, degrees ); // Q23 + return Mpy_32_32( PI_OVER_180_FX, degrees ); // Q22 } float deg2rad( diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 2aa3311b8..3de9a7f3b 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -128,7 +128,7 @@ Word32 sum_l_fx( const Word32 *vec, /* i : input vector */ const Word16 lvec /* i : length of input vector */ ); -Word16 norm_ul( UWord32 UL_var1 ); + Word32 Mult_32_16( Word32 a, diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 74a47dde8..6f40a49a5 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -242,26 +242,6 @@ void fix2f_16( Word16 *var_fix, float *var_flt, Word32 expo ) #undef WMC_TOOL_SKIP -int16_t norm_ul( uint32_t UL_var1 ) -{ - int16_t var_out; - - if ( UL_var1 == 0 ) - { - var_out = 0; - } - else - { - for ( var_out = 0; UL_var1 < (uint32_t) 0x80000000U; var_out++ ) - { - UL_var1 <<= 1; - } - } - BASOP_CHECK(); - - return ( var_out ); -} - /*-------------------------------------------------------------------* * usdequant_fx() * diff --git a/lib_com/typedef.h b/lib_com/typedef.h index 3d86229dd..36ff2e091 100644 --- a/lib_com/typedef.h +++ b/lib_com/typedef.h @@ -134,6 +134,8 @@ typedef float Float32; typedef unsigned short int UNS_Word16; /* 16 bit "register" (sw*) */ +typedef int Counter; + #ifndef TYPEDEF_INITIALIZED #error types in typedef.h not initialized #endif diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index ce4dfa9c9..60bdda941 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1839,8 +1839,8 @@ void ivas_binRenderer_fx( { FOR( k = 0; k < numTimeSlots; k++ ) { - set64_fx( Cldfb_RealBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); - set64_fx( Cldfb_ImagBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set64_fx( Cldfb_RealBuffer_Binaural_64fx[chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set64_fx( Cldfb_ImagBuffer_Binaural_64fx[chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); } } @@ -1848,8 +1848,8 @@ void ivas_binRenderer_fx( { FOR( k = 0; k < numTimeSlots; k++ ) { - mvr2r( RealBuffer_fx[chIdx][k], RealBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX ); - mvr2r( ImagBuffer_fx[chIdx][k], ImagBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX ); + Copy32( RealBuffer_fx[chIdx][k], RealBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX ); + Copy32( ImagBuffer_fx[chIdx][k], ImagBuffer_local[chIdx][k], CLDFB_NO_CHANNELS_MAX ); } } #else @@ -1935,7 +1935,7 @@ void ivas_binRenderer_fx( IF( GT_16( pMultiBinPoseData->num_poses, 1 ) ) { IVAS_QUATERNION Quaternions_rel, Quaternions_abs, *Quaternions_ref; - Word32 Rmat_local[3][3]; + Word32 Rmat_local[MAX_PARAM_SPATIAL_SUBFRAMES][3][3]; Word16 q_fact_orig; IF( hCombinedOrientationData && hBinRenderer->rotInCldfb ) @@ -1981,25 +1981,25 @@ void ivas_binRenderer_fx( modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig ); - QuatToRotMat_fx( Quaternions_abs, Rmat_local ); + QuatToRotMat_fx( Quaternions_abs, Rmat_local[0] ); - modify_Rmat_q_fx( Rmat_local, Rmat_local, MAX_PARAM_SPATIAL_SUBFRAMES, sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); + modify_Rmat_q_fx( Rmat_local, Rmat_local, 1, sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); if ( hBinRenderer->hInputSetup->is_loudspeaker_setup ) { - rotateFrame_sd_cldfb( Rmat_local, RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); + rotateFrame_sd_cldfb_fixed( Rmat_local[0], RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); } else { - rotateFrame_shd_cldfb( RealBuffer_fx, ImagBuffer_fx, Rmat_local, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 ); + rotateFrame_shd_cldfb( RealBuffer_fx, ImagBuffer_fx, Rmat_local[0], hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 ); } FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) { FOR( k = 0; k < numTimeSlots; k++ ) { - set64_fx( Cldfb_RealBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); - set64_fx( Cldfb_ImagBuffer_Binaural_64fx[pos_idx][chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set64_fx( Cldfb_RealBuffer_Binaural_64fx[chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); + set64_fx( Cldfb_ImagBuffer_Binaural_64fx[chIdx][k], 0, CLDFB_NO_CHANNELS_MAX ); } } ivas_binRenderer_filterModule_fx( Cldfb_RealBuffer_Binaural_64fx, Cldfb_ImagBuffer_Binaural_64fx, RealBuffer_fx, ImagBuffer_fx, numTimeSlots, hBinRenderer, pos_idx, *Q_in ); @@ -2099,7 +2099,7 @@ void ivas_rend_CldfbMultiBinRendProcess( Word32 Cldfb_Out_Imag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const Word16 low_res_pre_rend_rot, const Word16 num_subframes, - Word16 *Q_in /* i : LS signals exp */ + const Word16 Q_in /* i : LS signals exp */ ) { int16_t slot_idx, ch_idx, idx, pose_idx, i, j; @@ -2108,7 +2108,7 @@ void ivas_rend_CldfbMultiBinRendProcess( Word32 Cldfb_ImagBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; - Word16 Q_in_orig = *Q_in; + Word16 Q_in_orig = Q_in; move16(); FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) @@ -2142,7 +2142,7 @@ void ivas_rend_CldfbMultiBinRendProcess( move16(); } - ivas_binRenderer_fx( hCldfbRend, pMultiBinPoseData, *pCombinedOrientationData, MAX_PARAM_SPATIAL_SUBFRAMES, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer_sfIn, Cldfb_ImagBuffer_sfIn, Q_in ); + ivas_binRenderer_fx( hCldfbRend, pMultiBinPoseData, *pCombinedOrientationData, MAX_PARAM_SPATIAL_SUBFRAMES, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer_sfIn, Cldfb_ImagBuffer_sfIn, &Q_in_orig ); FOR( pose_idx = 0; pose_idx < hCldfbRend->numPoses; pose_idx++ ) { @@ -2153,12 +2153,11 @@ void ivas_rend_CldfbMultiBinRendProcess( { Copy32( &Cldfb_RealBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band ); Copy32( &Cldfb_ImagBuffer_Binaural[pose_idx][ch_idx][slot_idx][0], &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band ); - Scale_sig32( &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in_orig, *Q_in ) ); // Q_in_orig - Scale_sig32( &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in_orig, *Q_in ) ); // Q_in_orig + Scale_sig32( &Cldfb_Out_Real[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in, Q_in_orig ) ); // Q_in_orig + Scale_sig32( &Cldfb_Out_Imag[( pose_idx * BINAURAL_CHANNELS ) + ch_idx][idx][0], hCldfbRend->max_band, sub( Q_in, Q_in_orig ) ); // Q_in_orig } } } - *Q_in = Q_in_orig; } return; diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 46cb389bf..a8b2da904 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -3806,22 +3806,28 @@ void ivas_dirac_dec_render_sf_fx( hSpatParamRendCom->subframe_nbslots[subframe_idx], Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, Cldfb_RealBuffer_fx, Cldfb_ImagBuffer_fx, &input_q ); - +#ifndef SPLIT_REND_WITH_HEAD_ROT Scale_sig32( Cldfb_RealBuffer_Binaural_fx[0][0], i_mult( BINAURAL_CHANNELS, i_mult( MAX_PARAM_SPATIAL_SUBFRAMES, CLDFB_NO_CHANNELS_MAX ) ), sub( Q6, input_q ) ); // Q6 Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[0][0], i_mult( BINAURAL_CHANNELS, i_mult( MAX_PARAM_SPATIAL_SUBFRAMES, CLDFB_NO_CHANNELS_MAX ) ), sub( Q6, input_q ) ); // Q6 - +#else + Word16 pos_idx; + FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + { + Scale_sig32( &Cldfb_RealBuffer_Binaural_fx[pos_idx][0][0][0], i_mult( BINAURAL_CHANNELS, i_mult( MAX_PARAM_SPATIAL_SUBFRAMES, CLDFB_NO_CHANNELS_MAX ) ), sub( Q6, input_q ) ); // Q6 + Scale_sig32( &Cldfb_ImagBuffer_Binaural_fx[pos_idx][0][0][0], i_mult( BINAURAL_CHANNELS, i_mult( MAX_PARAM_SPATIAL_SUBFRAMES, CLDFB_NO_CHANNELS_MAX ) ), sub( Q6, input_q ) ); // Q6 + } +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - Word16 pos_idx; FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) { FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ ) { FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { - Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[( add( i_mult( pos_idx, BINAURAL_CHANNELS ) ), ch )][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); // Q6 - Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[( add( i_mult( pos_idx, BINAURAL_CHANNELS ) ), ch )][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); // Q6 + Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); // Q6 + Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_idx_start, slot_idx )], hSpatParamRendCom->num_freq_bands ); // Q6 } } } diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 8fe884c3f..29aacd01a 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1186,12 +1186,12 @@ ivas_error ivas_init_decoder_front( *--------------------------------------------------------------------*/ test(); test(); - IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || - ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) && st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || + ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) && st_ivas->hDecoderConfig->Opt_non_diegetic_pan ) ) +#else + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { IF( NE_32( ( error = ivas_render_config_open( &( st_ivas->hRenderConfig ) ) ), IVAS_ERR_OK ) ) { @@ -3500,7 +3500,7 @@ static ivas_error doSanityChecks_IVAS( } #ifdef SPLIT_REND_WITH_HEAD_ROT - IF( ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && NE_16( output_Fs, 48000 ) ) + IF( ( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && NE_32( output_Fs, 48000 ) ) { return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Error: Only 48kHz output sampling rate is supported for split rendering." ); } @@ -3510,11 +3510,11 @@ static ivas_error doSanityChecks_IVAS( { test(); test(); - IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) #endif - ) ) { return IVAS_ERROR( IVAS_ERR_HEAD_ROTATION_NOT_SUPPORTED, "Wrong set-up: Head-rotation not supported in this configuration" ); } diff --git a/lib_dec/ivas_init_dec_fx.c b/lib_dec/ivas_init_dec_fx.c index b0dbe97b4..47b17aa96 100644 --- a/lib_dec/ivas_init_dec_fx.c +++ b/lib_dec/ivas_init_dec_fx.c @@ -60,7 +60,11 @@ void ivas_init_dec_get_num_cldfb_instances_ivas_fx( move16(); } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( st_ivas->hDiracDecBin[0]->useTdDecorr ) +#else IF( st_ivas->hDiracDecBin->useTdDecorr ) +#endif { *numCldfbAnalyses = add( *numCldfbAnalyses, 2 ); move16(); diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 6f1ae3de8..a234caaba 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -198,11 +198,11 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( ivas_param_ism_dec_close_fx( &( st_ivas->hParamIsmDec ), &( st_ivas->hSpatParamRendCom ), st_ivas->hDecoderConfig->output_config ); test(); - IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { /* close the parametric binaural renderer */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -277,11 +277,11 @@ static ivas_error ivas_ism_bitrate_switching_dec_fx( } test(); - IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { /* open the parametric binaural renderer */ IF( NE_32( ( error = ivas_dirac_dec_binaural_copy_hrtfs_fx( &st_ivas->hHrtfParambin ) ), IVAS_ERR_OK ) ) diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index 50d1811f6..31d28961d 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -556,11 +556,11 @@ static ivas_error ivas_param_ism_rendering_init_fx( test(); test(); test(); - IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) #endif - ) ) { /* computation of proto matrix */ ivas_ism_get_proto_matrix_fx( hOutSetup, nchan_transport, hParamIsmRendering->proto_matrix_fx ); @@ -737,12 +737,13 @@ ivas_error ivas_param_ism_dec_open_fx( test(); test(); test(); - IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || - EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || + EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else + IF( !( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || + EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) ) #endif - ) ) { /* Initialize efap handle */ IF( NE_32( ( error = efap_init_data_fx( &( st_ivas->hEFAPdata ), hOutSetup.ls_azimuth_fx, hOutSetup.ls_elevation_fx, hOutSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) ) @@ -765,11 +766,11 @@ ivas_error ivas_param_ism_dec_open_fx( test(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { IF( NE_32( ( error = ivas_dirac_allocate_parameters_fx( hSpatParamRendCom, 1 ) ), IVAS_ERR_OK ) ) { diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 0f762462c..865a2d85e 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -1687,20 +1687,23 @@ void ivas_jbm_dec_feed_tc_to_renderer_fx( test(); test(); /* delay the objects here for all renderers where it is needed */ - IF( #ifdef SPLIT_REND_WITH_HEAD_ROT + IF( ( -#endif EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || EQ_16( st_ivas->renderer_type, RENDERER_OSBA_AMBI ) || EQ_16( st_ivas->renderer_type, RENDERER_OSBA_LS ) || - EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) -#ifdef SPLIT_REND_WITH_HEAD_ROT - ) && - ( NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) && + ( NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else + IF( + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || + EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) || + EQ_16( st_ivas->renderer_type, RENDERER_OSBA_AMBI ) || + EQ_16( st_ivas->renderer_type, RENDERER_OSBA_LS ) || + EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) #endif - ) { FOR( n = 0; n < st_ivas->nchan_ism; n++ ) { @@ -2081,7 +2084,7 @@ ivas_error ivas_jbm_dec_render_fx( { IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural_fx( st_ivas, p_output_fx, *nSamplesRendered ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output_fx, *nSamplesRendered ) ) != IVAS_ERR_OK ) { return error; } @@ -2415,7 +2418,7 @@ ivas_error ivas_jbm_dec_render_fx( #ifdef SPLIT_REND_WITH_HEAD_ROT IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_splitBinaural_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) { return error; } diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index e87d5da00..c547c4687 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1790,7 +1790,7 @@ ivas_error ivas_masa_dec_reconfigure_fx( IF( st_ivas->hDiracDecBin[pos_idx] != NULL ) { /* regularization factor is bitrate-dependent */ - st_ivas->hDiracDecBin[pos_idx]->reqularizationFactor = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); + st_ivas->hDiracDecBin[pos_idx]->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); move16(); } } diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 7e96c0717..078268dc4 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -2227,6 +2227,20 @@ void ivas_param_mc_dec_render_fx( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; + FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + { + FOR( Word16 idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) + { + FOR( Word16 idx2 = 0; idx2 < hParamMC->subframe_nbslots[subframe_idx]; idx2++ ) + { + Scale_sig32( Cldfb_RealBuffer_Binaural_fx[pos_idx][idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( Q6, input_q ) ); // Q6 + Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( Q6, input_q ) ); // Q6 + } + } + } +#else FOR( Word16 idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) { FOR( Word16 idx2 = 0; idx2 < hParamMC->subframe_nbslots[subframe_idx]; idx2++ ) @@ -2235,11 +2249,11 @@ void ivas_param_mc_dec_render_fx( Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( Q6, input_q ) ); // Q6 } } +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - int16_t pos_idx; FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) { FOR( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++ ) diff --git a/lib_dec/ivas_mc_paramupmix_dec.c b/lib_dec/ivas_mc_paramupmix_dec.c index f998b0d1b..08606c8f1 100644 --- a/lib_dec/ivas_mc_paramupmix_dec.c +++ b/lib_dec/ivas_mc_paramupmix_dec.c @@ -866,8 +866,8 @@ static void ivas_mc_paramupmix_dec_sf( { FOR( ch = 0; ch < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); ch++ ) { - Copy32( Cldfb_RealBuffer_subfr[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer[ch][add( slot_index_start, slot_idx )], maxBand ); - Copy32( Cldfb_ImagBuffer_subfr[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer[ch][add( slot_index_start, slot_idx )], maxBand ); + Copy32( Cldfb_RealBuffer_subfr_fx[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer_fx[ch][add( slot_index_start, slot_idx )], maxBand ); + Copy32( Cldfb_ImagBuffer_subfr_fx[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer_fx[ch][add( slot_index_start, slot_idx )], maxBand ); } } @@ -888,7 +888,20 @@ static void ivas_mc_paramupmix_dec_sf( Cldfb_RealBuffer_subfr_fx, Cldfb_ImagBuffer_subfr_fx, &input_q ); - +#ifdef SPLIT_REND_WITH_HEAD_ROT + int16_t pos_idx; + FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + { + FOR( Word16 idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) + { + FOR( Word16 idx2 = 0; idx2 < MAX_PARAM_SPATIAL_SUBFRAMES; idx2++ ) + { + Scale_sig32( Cldfb_RealBuffer_Binaural_fx[pos_idx][idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( 6, input_q ) ); // Q6 + Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( 6, input_q ) ); // Q6 + } + } + } +#else FOR( Word16 idx1 = 0; idx1 < BINAURAL_CHANNELS; idx1++ ) { FOR( Word16 idx2 = 0; idx2 < MAX_PARAM_SPATIAL_SUBFRAMES; idx2++ ) @@ -897,19 +910,19 @@ static void ivas_mc_paramupmix_dec_sf( Scale_sig32( Cldfb_ImagBuffer_Binaural_fx[idx1][idx2], CLDFB_NO_CHANNELS_MAX, sub( 6, input_q ) ); // Q6 } } +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - int16_t pos_idx; FOR( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) { FOR( slot_idx = 0; slot_idx < st_ivas->hTcBuffer->subframe_nbslots[subframeIdx]; slot_idx++ ) { FOR( ch = 0; ch < st_ivas->hDecoderConfig->nchan_out; ch++ ) { - Copy32( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); - Copy32( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); + Copy32( Cldfb_RealBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); + Copy32( Cldfb_ImagBuffer_Binaural_fx[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[add( i_mult( pos_idx, BINAURAL_CHANNELS ), ch )][add( slot_index_start, slot_idx )], maxBand ); } } } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 8e34d6642..ec9cc8b12 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -1455,11 +1455,11 @@ static ivas_error ivas_mc_dec_reconfig_fx( test(); test(); test(); - IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { /* remove unneeded binaural renderers */ test(); diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index b4f757025..0079ae4de 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -813,7 +813,7 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); n++ ) { - p_rend_obj[n] = &output_f[n][0]; + p_rend_obj[n] = &output_fx[n][0]; move32(); } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index b71b73a6a..1c008caa0 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -176,7 +176,7 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( move16(); st_ivas->nchan_transport = st_ivas->nchan_ism; move16(); - IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, output_f, *nSamplesRendered ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, output_fx, *nSamplesRendered ) ) != IVAS_ERR_OK ) { return error; } @@ -188,18 +188,19 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( { FOR( slot_idx = 0; slot_idx < cldfb_slots; slot_idx++ ) { - cldfbAnalysis_ts_fx_fixed_q( &( output_f[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb ); + cldfbAnalysis_ts_fx_fixed_q( &( output_fx[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb ); + Scale_sig32( Cldfb_RealBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); FOR( b = 0; b < num_cldfb_bands; b++ ) { - st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][slot_idx_start + slot_idx][b] = - L_add( L_shr( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[n][add( slot_idx_start, slot_idx )][b], 1 ), + st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx][b] = + L_add( L_shr( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][add( slot_idx_start, slot_idx )][b], 1 ), L_shr( Cldfb_RealBuffer[b], 1 ) ); move32(); - st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][slot_idx_start + slot_idx][b] = - L_add( L_shr( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[n][add(slot_idx_start, slot_idx)][b], 1 ), - L_shrCldfb_ImagBuffer[b], 1) ); + st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx][b] = + L_add( L_shr( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][add( slot_idx_start, slot_idx )][b], 1 ), + L_shr( Cldfb_ImagBuffer[b], 1 ) ); move32(); } } diff --git a/lib_dec/ivas_output_config.c b/lib_dec/ivas_output_config.c index d2aad8218..a3f361e1e 100644 --- a/lib_dec/ivas_output_config.c +++ b/lib_dec/ivas_output_config.c @@ -81,11 +81,11 @@ void ivas_renderer_select( test(); test(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { test(); test(); @@ -96,11 +96,11 @@ void ivas_renderer_select( { IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) { - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) #endif - ) { *renderer_type = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -114,11 +114,11 @@ void ivas_renderer_select( ELSE /* ISM_MODE_DISC */ { test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { *renderer_type = RENDERER_BINAURAL_OBJECTS_TD; move16(); @@ -138,12 +138,11 @@ void ivas_renderer_select( { *internal_config = output_config; move16(); - - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) #endif - ) { *renderer_type = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -160,11 +159,11 @@ void ivas_renderer_select( move16(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { *renderer_type = RENDERER_BINAURAL_FASTCONV; move16(); @@ -219,11 +218,11 @@ void ivas_renderer_select( *internal_config = output_config; move16(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) #endif - ) { *renderer_type = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -239,11 +238,11 @@ void ivas_renderer_select( *internal_config = transport_config; move16(); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { test(); test(); diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index f1ac7fa76..daf624a78 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -185,11 +185,11 @@ ivas_error ivas_sba_dec_reconfigure_fx( test(); test(); test(); - IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) +#else + IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) && ( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) #endif - ) ) { RENDERER_TYPE renderer_type_new; Word16 sba_order_internal; @@ -200,11 +200,11 @@ ivas_error ivas_sba_dec_reconfigure_fx( /* copy the logic from ivas_renderer_select(), because calling this function has too many side effects that would affect the flushing */ IF( LE_16( ivas_get_sba_num_TCs_fx( ivas_total_brate, sba_order_internal ), 2 ) ) { - IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) ) #endif - ) { renderer_type_new = RENDERER_BINAURAL_PARAMETRIC; move16(); @@ -218,11 +218,11 @@ ivas_error ivas_sba_dec_reconfigure_fx( ELSE { test(); - IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) +#else + IF( EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) #endif - ) { renderer_type_new = RENDERER_BINAURAL_FASTCONV; move16(); diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index 760d12a36..ebccb336f 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -2002,12 +2002,13 @@ void ivas_spar_dec_upmixer_sf_fx( test(); test(); test(); - IF( ( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || !( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) -#endif - ) ) && + IF( ( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || !( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) ) && + !( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) ) +#else + IF( ( EQ_32( hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || !( EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( st_ivas->hOutSetup.output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) ) && !( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) ) +#endif { Scale_sig32( st_ivas->cldfbSynDec[idx_in]->cldfb_state_fx, st_ivas->cldfbSynDec[idx_in]->p_filter_length, -6 ); /*st_ivas->cldfbSynDec[idx_in]->Q_cldfb_state-6*/ st_ivas->cldfbSynDec[idx_in]->Q_cldfb_state = sub( st_ivas->cldfbSynDec[idx_in]->Q_cldfb_state, 6 ); diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 8e1edc657..2e6085494 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -2268,11 +2268,19 @@ ivas_error IVAS_DEC_FeedHeadTrackData( /* Move head-tracking data to the decoder handle */ /* check for Euler angle signaling */ - // TODO change euler angle to Q22 format +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* check for Euler angle signaling */ + IF( EQ_32( orientation.w_fx, L_negate( 12582912 ) ) && EQ_16( orientation.q_fact, Q22 ) ) + { + Euler2Quat_fx( deg2rad_fx( orientation.x_fx ), deg2rad_fx( orientation.y_fx ), deg2rad_fx( orientation.z_fx ), &orientation ); + modify_Quat_q_fx( &orientation, &orientation, Q29 ); + } +#else IF( EQ_32( orientation.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) { Euler2Quat_fx( deg2rad_fx( orientation.x_fx ), deg2rad_fx( orientation.y_fx ), deg2rad_fx( orientation.z_fx ), &orientation ); } +#endif Word32 updateRate_fx = 1677721600; // value is 200 in Q23 move32(); diff --git a/lib_isar/isar_PredDecoder.c b/lib_isar/isar_PredDecoder.c index 3fa9ec877..eab82fe12 100644 --- a/lib_isar/isar_PredDecoder.c +++ b/lib_isar/isar_PredDecoder.c @@ -39,7 +39,6 @@ #include "isar_lcld_prot.h" #include "isar_lcld_rom_tables.h" #include "wmc_auto.h" -#include "basop_mpy.h" /*-------------------------------------------------------------------* * Function CreatePredictionDecoder() diff --git a/lib_isar/isar_PredEncoder.c b/lib_isar/isar_PredEncoder.c index 0ca4d7add..d2b6e0f5c 100644 --- a/lib_isar/isar_PredEncoder.c +++ b/lib_isar/isar_PredEncoder.c @@ -39,7 +39,7 @@ #include "prot.h" #include "isar_prot.h" #include "wmc_auto.h" -#include "prot_fx2.h" +#include "prot_fx.h" #include "basop_util.h" #include "enh64.h" #include "basop32.h" diff --git a/lib_isar/isar_RMSEnvGrouping.c b/lib_isar/isar_RMSEnvGrouping.c index 0c24040be..450356d02 100644 --- a/lib_isar/isar_RMSEnvGrouping.c +++ b/lib_isar/isar_RMSEnvGrouping.c @@ -40,7 +40,7 @@ #include "isar_lcld_prot.h" #include "isar_lcld_rom_tables.h" #include "wmc_auto.h" -#include "prot_fx2.h" +#include "prot_fx.h" #include "basop_util.h" #include "enh64.h" Word32 Inv_grp_length[17] = { diff --git a/lib_isar/isar_lcld_decoder.c b/lib_isar/isar_lcld_decoder.c index c067ad064..2695b397d 100644 --- a/lib_isar/isar_lcld_decoder.c +++ b/lib_isar/isar_lcld_decoder.c @@ -40,7 +40,7 @@ #include "isar_prot.h" #include "wmc_auto.h" #include "basop_util.h" -#include "prot_fx2.h" +#include "prot_fx.h" // #define DEBUG_WRITE #include "debug.h" #include "enh64.h" diff --git a/lib_isar/isar_lcld_encoder.c b/lib_isar/isar_lcld_encoder.c index aa9332c26..784f6f92e 100644 --- a/lib_isar/isar_lcld_encoder.c +++ b/lib_isar/isar_lcld_encoder.c @@ -38,13 +38,12 @@ #include "isar_lcld_prot.h" #include "isar_lcld_rom_tables.h" #include "prot.h" -#include "prot_fx2.h" +#include "prot_fx.h" #include "isar_prot.h" #include "wmc_auto.h" #include "basop_util.h" #include "enh64.h" #include "basop32.h" -#include "basop_mpy.h" #define LOG10_2_FX ( 646456993 ) /*------------------------------------------------------------------------------------------* diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h index 24f93b283..331eaadf3 100644 --- a/lib_isar/isar_prot.h +++ b/lib_isar/isar_prot.h @@ -136,9 +136,6 @@ void isar_splitBinLCLDDecProcess( void set_fix_rotation_mat_fx( Word32 fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); -void set_fix_rotation_mat( - float fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); void isar_splitBinLCLDEncClose( ISAR_BIN_HR_SPLIT_LCLD_ENC_HANDLE *hSplitBinLCLDEnc ); @@ -153,9 +150,6 @@ void isar_splitBinLCLDEncProcess( void set_pose_types_fx( ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); -void set_pose_types( - ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); void isar_split_rend_init_huff_cfg( ISAR_BIN_HR_SPLIT_REND_HUFF_HANDLE pHuff_cfg ); @@ -275,8 +269,6 @@ void isar_init_multi_bin_pose_data_fx( /* Copy for encoder, to be removed */ void isar_init_multi_bin_pose_data_fx_enc( MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); -void isar_init_multi_bin_pose_data( - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ); void isar_rend_CldfbSplitPreRendProcess( const ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, @@ -460,6 +452,13 @@ void set32_fx( Word16 ceil_log_2( UWord64 val ); + +void ivas_cmult_fix( Word32 in1_re_fx, Word16 exp_re1, Word32 in1_im_fx, Word16 exp_im1, Word32 in2_re_fx, Word16 exp_re2, Word32 in2_im_fx, Word16 exp_im2, Word32 *out1_re_fx, Word32 *out1_im_fx, Word16 *exp_out1_re, Word16 *exp_out1_im ); + +void ivas_calculate_abs_fx( Word32 re_fx, Word16 exp_re, Word32 im_fx, Word16 exp_im, Word32 *out_fx, Word16 *exp_out ); + +void ivas_calculate_rabs_fx( Word32 re_fx, Word16 exp_re, Word32 *out_fx, Word16 *exp_out ); + /* clang-format on */ #endif /* IVAS_PROT_REND_H */ diff --git a/lib_isar/isar_splitRendererPLC.c b/lib_isar/isar_splitRendererPLC.c index 5d2f02af6..5266cfd6b 100644 --- a/lib_isar/isar_splitRendererPLC.c +++ b/lib_isar/isar_splitRendererPLC.c @@ -64,24 +64,6 @@ #define PLC_FADE_CNST SR_PLC_FADE_START *CLDFB_NO_COL_MAX #define PLC_MUTE_CNST SR_PLC_MUTE *CLDFB_NO_COL_MAX Word32 xf_alp_tab[CLDFB_PLC_XF] = { 1431655680, 715827840 }; -static Word16 find_guarded_bits_fx( Word32 n ) -{ - return n <= 1 ? 0 : n <= 2 ? 1 - : n <= 4 ? 2 - : n <= 8 ? 3 - : n <= 16 ? 4 - : n <= 32 ? 5 - : n <= 64 ? 6 - : n <= 128 ? 7 - : n <= 256 ? 8 - : n <= 512 ? 9 - : n <= 1024 ? 10 - : n <= 2048 ? 11 - : n <= 4096 ? 12 - : n <= 8192 ? 13 - : n <= 16384 ? 14 - : 15; -} /*------------------------------------------------------------------------- * Function adaptive_polar_ext_plc() diff --git a/lib_isar/isar_splitRendererPost.c b/lib_isar/isar_splitRendererPost.c index 840b102d0..c313e9ca4 100644 --- a/lib_isar/isar_splitRendererPost.c +++ b/lib_isar/isar_splitRendererPost.c @@ -38,6 +38,7 @@ #include #endif #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "prot.h" #include "isar_rom_post_rend.h" #include "isar_prot.h" @@ -86,11 +87,11 @@ ivas_error isar_splitBinPostRendOpen( FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - IF( ( error = openCldfb_splitRend( &( hBinRend->cldfbSyn[ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + IF( ( error = openCldfb_ivas_fx( &( hBinRend->cldfbSyn[ch] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) { return error; } - IF( ( error = openCldfb_splitRend( &( hBinRend->cldfbAna[ch] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + IF( ( error = openCldfb_ivas_fx( &( hBinRend->cldfbAna[ch] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) { return error; } @@ -134,12 +135,12 @@ void isar_splitBinPostRendClose( { IF( ( *hBinHrSplitPostRend )->cldfbSyn[ch] != NULL ) { - deleteCldfb_splitRend( &( ( *hBinHrSplitPostRend )->cldfbSyn[ch] ) ); + deleteCldfb_ivas_fx( &( ( *hBinHrSplitPostRend )->cldfbSyn[ch] ) ); ( *hBinHrSplitPostRend )->cldfbSyn[ch] = NULL; } IF( ( *hBinHrSplitPostRend )->cldfbAna[ch] != NULL ) { - deleteCldfb_splitRend( &( ( *hBinHrSplitPostRend )->cldfbAna[ch] ) ); + deleteCldfb_ivas_fx( &( ( *hBinHrSplitPostRend )->cldfbAna[ch] ) ); ( *hBinHrSplitPostRend )->cldfbAna[ch] = NULL; } } diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 12e684767..092358962 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -38,6 +38,7 @@ #include #endif #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "prot.h" #include "lib_isar_pre_rend.h" #include "isar_rom_post_rend.h" @@ -2375,12 +2376,6 @@ static void isar_SplitRenderer_quant_code( * *------------------------------------------------------------------------*/ -static Word16 imult1616( Word16 x, Word16 y ) -{ - assert( (int) x * (int) y < 32768 && (int) x * (int) y >= -32768 ); - return extract_l( L_mult0( x, y ) ); -} - static void isar_SplitRenderer_GetRotMd_fx( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, /* i/o: binaural renderer handle */ MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, diff --git a/lib_isar/isar_splitRenderer_utils.c b/lib_isar/isar_splitRenderer_utils.c index b290ca12a..3e2dd1f41 100644 --- a/lib_isar/isar_splitRenderer_utils.c +++ b/lib_isar/isar_splitRenderer_utils.c @@ -49,7 +49,7 @@ #endif #include "wmc_auto.h" #include "basop_settings.h" -#include "prot_fx2.h" +#include "prot_fx.h" #include "basop_util.h" @@ -439,29 +439,6 @@ void set_fix_rotation_mat_fx( return; } -void set_fix_rotation_mat( - float fix_pos_rot_mat[][BINAURAL_CHANNELS][BINAURAL_CHANNELS], - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) -{ - float yaw_a, cos_yaw, sin_yaw; - int16_t pos_idx; - yaw_a = 0.0f; - - for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) - { - yaw_a = pMultiBinPoseData->relative_head_poses[pos_idx + 1][0]; - cos_yaw = cosf( EVS_PI * yaw_a / 180.0f ); - sin_yaw = sinf( EVS_PI * yaw_a / 180.0f ); - sin_yaw = 0.0f; - fix_pos_rot_mat[pos_idx][0][0] = cos_yaw; - fix_pos_rot_mat[pos_idx][1][1] = cos_yaw; - fix_pos_rot_mat[pos_idx][0][1] = sin_yaw; - fix_pos_rot_mat[pos_idx][1][0] = -1.0f * sin_yaw; - } - - return; -} - /*------------------------------------------------------------------------- * Function set_pose_types() @@ -496,30 +473,6 @@ void set_pose_types_fx( return; } -void set_pose_types( - ISAR_SPLIT_REND_POSE_TYPE pose_type[MAX_HEAD_ROT_POSES - 1], - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) -{ - int16_t pos_idx; - - for ( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses - 1; pos_idx++ ) - { - if ( fabs( pMultiBinPoseData->relative_head_poses[pos_idx + 1][0] ) > EPSILON ) - { - pose_type[pos_idx] = ANY_YAW; - } - else if ( fabs( pMultiBinPoseData->relative_head_poses[pos_idx + 1][2] ) > EPSILON ) - { - pose_type[pos_idx] = ANY_ROLL; - } - else - { - pose_type[pos_idx] = PITCH_ONLY; - } - } - - return; -} /*------------------------------------------------------------------------- @@ -1512,24 +1465,6 @@ void isar_init_multi_bin_pose_data_fx_enc( return; } -void isar_init_multi_bin_pose_data( - MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData ) -{ - int16_t pos_idx; - - for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ ) - { - pMultiBinPoseData->relative_head_poses[pos_idx][0] = 0.0f; - pMultiBinPoseData->relative_head_poses[pos_idx][1] = 0.0f; - pMultiBinPoseData->relative_head_poses[pos_idx][2] = 0.0f; - } - pMultiBinPoseData->num_poses = 1; - pMultiBinPoseData->dof = 3; - pMultiBinPoseData->hq_mode = 0; - pMultiBinPoseData->rot_axis = DEFAULT_AXIS; - - return; -} #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS ivas_error isar_framesize_to_ms( diff --git a/lib_isar/lib_isar_post_rend.c b/lib_isar/lib_isar_post_rend.c index 178718a60..128675281 100644 --- a/lib_isar/lib_isar_post_rend.c +++ b/lib_isar/lib_isar_post_rend.c @@ -37,7 +37,8 @@ #include "isar_prot.h" #include "prot.h" #include "ivas_prot.h" -#include "prot_fx2.h" +#include "ivas_prot_fx.h" +#include "prot_fx.h" #ifndef SPLIT_REND_WITH_HEAD_ROT int32_t ISAR_POST_REND_void_func( void ) @@ -51,7 +52,7 @@ int32_t ISAR_POST_REND_void_func( void ) #include #include #include "wmc_auto.h" -#include "prot_fx2.h" +#include "prot_fx.h" /*-------------------------------------------------------------------* @@ -170,6 +171,7 @@ ISAR_POST_REND_AudioConfigType isar_getAudioConfigType( /*-------------------------------------------------------------------* * Local functions *-------------------------------------------------------------------*/ + static ivas_error allocateInputBaseBufferData_fx( Word32 **data, const Word16 data_size ) @@ -387,10 +389,10 @@ static ivas_error initLimiter( /* Support re-init: close if already allocated */ IF( *phLimiter != NULL ) { - ivas_limiter_close_splitRend( phLimiter ); + ivas_limiter_close_fx( phLimiter ); } - IF( ( error = ivas_limiter_open_splitRend( phLimiter, numChannels, sampleRate ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_limiter_open_fx( phLimiter, numChannels, sampleRate ) ) != IVAS_ERR_OK ) { return error; } @@ -1666,7 +1668,7 @@ static ivas_error renderSplitBinauralWithPostRot( } Q_max = s_min( Q_max, Q13 ); accumulate2dArrayToBuffer_fx( tmpCrendBuffer_fx, Q_out, Q_max, &outAudio, num_subframes, outBufNumSamplesPerChannel ); - *outAudio.q_data_fx = Q_max; + *outAudio.pq_fact = Q_max; pop_wmops(); return error; @@ -1793,8 +1795,8 @@ ivas_error ISAR_POST_REND_getSamples( #ifdef DEBUGGING hIvasRend->numClipping += #endif - Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.q_data_fx ); - limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.q_data_fx ); + Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); + limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact ); #endif return IVAS_ERR_OK; @@ -1847,7 +1849,7 @@ void ISAR_POST_REND_Close( clearInputSplitRend( &hIvasRend->inputsSplitPost[i] ); } - ivas_limiter_close_splitRend( &hIvasRend->hLimiter ); + ivas_limiter_close_fx( &hIvasRend->hLimiter ); free( hIvasRend ); *phIvasRend = NULL; diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 44fe32f4a..bafb68a15 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -157,9 +157,9 @@ ivas_error ISAR_PRE_REND_open( FOR( ch = 0; ch < num_ch; ch++ ) { - if ( ( error = openCldfb( &( hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] ), - CLDFB_ANALYSIS, - OutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + if ( ( error = openCldfb_ivas_fx( &( hSplitRendWrapper->hCldfbHandles->cldfbAna[ch] ), + CLDFB_ANALYSIS, + OutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) { return error; } @@ -167,7 +167,7 @@ ivas_error ISAR_PRE_REND_open( FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - IF( ( error = openCldfb( &( hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] ), CLDFB_SYNTHESIS, OutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + IF( ( error = openCldfb_ivas_fx( &( hSplitRendWrapper->hCldfbHandles->cldfbSyn[ch] ), CLDFB_SYNTHESIS, OutSampleRate, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_lc3plus/apply_global_gain_fx.c b/lib_lc3plus/apply_global_gain_fx.c index 7c5220f10..a3299d863 100644 --- a/lib_lc3plus/apply_global_gain_fx.c +++ b/lib_lc3plus/apply_global_gain_fx.c @@ -11,7 +11,7 @@ void processApplyGlobalGain_fx(Word32 x[], Word16 *x_e, Word16 xLen, Word16 global_gain_idx, Word16 global_gain_off) { - Counter i; + Word32 i; #ifdef ENABLE_HR_MODE Word32 global_gain; #else diff --git a/lib_lc3plus/ari_codec.c b/lib_lc3plus/ari_codec.c index 8092aa28e..46ad0a532 100644 --- a/lib_lc3plus/ari_codec.c +++ b/lib_lc3plus/ari_codec.c @@ -99,7 +99,7 @@ Word16 processAriEncoder_fx(UWord8 *bytes, Word16 bp_side_in, Word16 mask_side_i Dyn_Mem_Deluxe_In(Encoder_State_fx st; Word16 bp, bp_side, mask_side, extra_bits; Word32 a1, b1, a1_i, b1_i, a1_msb, b1_msb; Word16 lev1; Word16 nbits_side; Word16 tmp; - Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Counter i, n, k, lev;); + Word16 fill_bits; UWord8 * ptr; Word16 numResBitsEnc; Word16 * lsb, nlsbs; Word32 i, n, k, lev;); lsb = (Word16 *)scratchAlign(scratchBuffer, 0); /* size = 2 * lastnz */ @@ -777,8 +777,8 @@ void processAriDecoder_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Wor Word16 lsb_ind_c; Word16 * lsb_ind; Word16 tmp; - Counter n, k, lev; - Counter i; + Word32 n, k, lev; + Word32 i; Word16 max_lev = 14; #ifdef DYNMEM_COUNT @@ -1711,7 +1711,7 @@ void processAriDecoderScaling_fx( # endif Word16 dataLen, Word32 *data32, Word16 *data_e) { - Counter i; + Word32 i; # ifdef ENABLE_HR_MODE Dyn_Mem_Deluxe_In(Word16 shift; Word32 tmp, x_min, x_max;); @@ -1802,7 +1802,7 @@ Word16 find_last_nz_pair(const Word32 x[], Word16 length) Word16 find_last_nz_pair(const Word16 x[], Word16 length) #endif { - Dyn_Mem_Deluxe_In(Word16 last_nz, lobs[4]; Counter stage, i;); + Dyn_Mem_Deluxe_In(Word16 last_nz, lobs[4]; Word32 stage, i;); lobs[0] = 4; move16(); @@ -1866,7 +1866,7 @@ void write_bit_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 bit) void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, Word16 numbits) { - Dyn_Mem_Deluxe_In(Counter k; Word16 bit;); + Dyn_Mem_Deluxe_In(Word32 k; Word16 bit;); FOR (k = 0; k < numbits; k++) { @@ -1881,7 +1881,7 @@ void write_indice_backward(UWord8 *ptr, Word16 *bp, Word16 *mask, Word16 indice, static __forceinline void write_indice_forward(UWord8 *ptr, Word16 bp, Word16 indice, Word16 numbits) { - Dyn_Mem_Deluxe_In(Counter k; Word16 bit, mask, tmp;); + Dyn_Mem_Deluxe_In(Word32 k; Word16 bit, mask, tmp;); tmp = (Word16)ptr[bp]; move16(); @@ -2093,7 +2093,7 @@ __forceinline Word16 read_bit(UWord8 *ptr, Word16 *bp, Word16 *mask) static __forceinline void ac_dec_init_fx(UWord8 *ptr, Word16 *bp, Word16 *bp_side, Word16 *mask_side, Decoder_State_fx *st_fx) /* i/o: Decoder State */ { - Dyn_Mem_Deluxe_In(Counter i;); + Dyn_Mem_Deluxe_In(Word32 i;); st_fx->ac_low_fx = L_deposit_l(0); diff --git a/lib_lc3plus/basop_util_lc3plus.c b/lib_lc3plus/basop_util_lc3plus.c index 55a9b9eb1..e3ab30f70 100644 --- a/lib_lc3plus/basop_util_lc3plus.c +++ b/lib_lc3plus/basop_util_lc3plus.c @@ -856,7 +856,7 @@ Word16 BASOP_Util_Cmp_Mant32Exp_lc3plus /*!< o: flag: result of comparison */ * mantissa (Q31) * *----------------------------------------------------------------------------------*/ -Word32 Isqrt(Word32 x, /* mantissa */ +Word32 Isqrt_lc3plus(Word32 x, /* mantissa */ Word16 *x_e /* pointer to exponent */ ) { diff --git a/lib_lc3plus/basop_util_lc3plus.h b/lib_lc3plus/basop_util_lc3plus.h index 99bc211a9..5f4f5c56b 100644 --- a/lib_lc3plus/basop_util_lc3plus.h +++ b/lib_lc3plus/basop_util_lc3plus.h @@ -299,7 +299,7 @@ void Copy_Scale_sig_32(const Word32 x[], /* i : signal to scale input ); #endif -Word32 Isqrt(Word32 x, /* (i) Q31: normalized value (1.0 > x >= 0.5) */ +Word32 Isqrt_lc3plus(Word32 x, /* (i) Q31: normalized value (1.0 > x >= 0.5) */ Word16 *x_e /* (i/o) Q0 : pointer to exponent */ ); diff --git a/lib_lc3plus/cutoff_bandwidth.c b/lib_lc3plus/cutoff_bandwidth.c index 05f7cce49..8ab047c81 100644 --- a/lib_lc3plus/cutoff_bandwidth.c +++ b/lib_lc3plus/cutoff_bandwidth.c @@ -11,7 +11,7 @@ void process_cutoff_bandwidth(Word32 d_fx[], Word16 len, Word16 bw_bin) { - Counter i = 0; + Word32 i = 0; if (len > bw_bin){ /* roll off */ for (i = -1; i < 3; i++) { diff --git a/lib_lc3plus/dct4_fx.c b/lib_lc3plus/dct4_fx.c index af98a395d..9f12894f4 100644 --- a/lib_lc3plus/dct4_fx.c +++ b/lib_lc3plus/dct4_fx.c @@ -35,7 +35,7 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ Word32 accu3; Word32 accu4; - Counter i; + Word32 i; #ifdef ENABLE_HR_MODE const PWord32 *twiddle; diff --git a/lib_lc3plus/dec_entropy.c b/lib_lc3plus/dec_entropy.c index 48512f9fe..572438615 100644 --- a/lib_lc3plus/dec_entropy.c +++ b/lib_lc3plus/dec_entropy.c @@ -26,7 +26,7 @@ void processDecoderEntropy_fx(UWord8 *bytes, Word16 *bp_side, Word16 *mask_side, Word16 L, submodeLSB; Word32 tmp32, tmp32lim; Word16 gain_e, gain, submodeMSB, BER_detect; - Counter n; + Word32 n; UWord8 *ptr; ); diff --git a/lib_lc3plus/ltpf_coder_fx.c b/lib_lc3plus/ltpf_coder_fx.c index 212788d73..d17daa1b9 100644 --- a/lib_lc3plus/ltpf_coder_fx.c +++ b/lib_lc3plus/ltpf_coder_fx.c @@ -139,7 +139,7 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo shift = norm_l(prod); prod = L_shl_pos(prod, shift); prod_exp = sub(62, add(add(scale1, scale2), shift)); - inv = Isqrt(prod, &prod_exp); + inv = Isqrt_lc3plus(prod, &prod_exp); scale0 = norm_l(sum0); sum0 = L_shl_pos(sum0, scale0); prod = Mpy_32_32_lc3plus(sum0, inv); @@ -257,7 +257,7 @@ void process_ltpf_coder_fx(Word16 *bits, Word16 ol_pitch, Word16 ltpf_enable, Wo shift = norm_l(prod); prod = L_shl_pos(prod, shift); prod_exp = sub(62, add(add(scale1, scale2), shift)); - inv = Isqrt(prod, &prod_exp); + inv = Isqrt_lc3plus(prod, &prod_exp); scale0 = norm_l(sum0); sum0 = L_shl_pos(sum0, scale0); prod = Mpy_32_32_lc3plus(sum0, inv); diff --git a/lib_lc3plus/olpa_fx.c b/lib_lc3plus/olpa_fx.c index a72d8b61c..a93a0ba25 100644 --- a/lib_lc3plus/olpa_fx.c +++ b/lib_lc3plus/olpa_fx.c @@ -176,7 +176,7 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] shift = norm_l(prod); prod = L_shl_pos(prod, shift); prod_exp = sub(62, add(add(scale1, scale2), shift)); - inv = Isqrt(prod, &prod_exp); + inv = Isqrt_lc3plus(prod, &prod_exp); scale0 = norm_l(sum0); sum0 = L_shl_pos(sum0, scale0); prod = Mpy_32_32_lc3plus(sum0, inv); @@ -225,7 +225,7 @@ void process_olpa_fx(Word16 *mem_s6k4_exp, Word16 mem_s12k8[], Word16 mem_s6k4[] shift = norm_l(prod); prod = L_shl_pos(prod, shift); prod_exp = sub(62, add(add(scale1, scale2), shift)); - inv = Isqrt(prod, &prod_exp); + inv = Isqrt_lc3plus(prod, &prod_exp); scale0 = norm_l(sum0); sum0 = L_shl_pos(sum0, scale0); prod = Mpy_32_32_lc3plus(sum0, inv); diff --git a/lib_lc3plus/plc_xcorr_fx.c b/lib_lc3plus/plc_xcorr_fx.c index 720015295..1a4782c32 100644 --- a/lib_lc3plus/plc_xcorr_fx.c +++ b/lib_lc3plus/plc_xcorr_fx.c @@ -145,7 +145,7 @@ Word16 plc_norm_corr_blocks_fx( /* o: norm_corr range [-1 shift = norm_l(L_prod); L_prod = L_shl_pos(L_prod, shift); prod_exp = sub(62, add(add(scale1, scale2), shift)); - L_inv = Isqrt(L_prod, &prod_exp); + L_inv = Isqrt_lc3plus(L_prod, &prod_exp); L_tmp0 = L_shl_pos(L_tmp0, scale0); L_prod = Mpy_32_32_lc3plus(L_tmp0, L_inv); diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index 4a4cce092..faf696393 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -193,9 +193,9 @@ static ivas_error ivas_rend_initCrend_fx( test(); test(); - IF( NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + if ( NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) #endif ) { @@ -1835,9 +1835,9 @@ void ivas_rend_closeCldfbRend( pCldfbRend->hCldfbRend->hInputSetup = NULL; } - ivas_binRenderer_close( &pCldfbRend->hCldfbRend ); + ivas_binRenderer_close_fx( &pCldfbRend->hCldfbRend ); ivas_binaural_hrtf_close( &pCldfbRend->hHrtfFastConv ); - ivas_HRTF_fastconv_binary_close( &pCldfbRend->hHrtfFastConv ); + ivas_HRTF_fastconv_binary_close_fx( &pCldfbRend->hHrtfFastConv ); return; } @@ -2440,7 +2440,7 @@ ivas_error ivas_rend_crendProcessSplitBin( Word16 sf; Word16 pos_idx, output_frame; ivas_error error; - Word32 gain_lfe; + Word16 gain_lfe; Word32 tmpLfeBuffer[L_FRAME48k]; Word32 tmpInputBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; Word32 *p_tmpInputBuffer[MAX_OUTPUT_CHANNELS]; @@ -2601,7 +2601,7 @@ ivas_error ivas_rend_crendProcessSubframesSplitBin( Word16 sf; Word16 pos_idx; ivas_error error; - Word32 gain_lfe; + Word16 gain_lfe; Word32 tmpLfeBuffer[L_FRAME48k]; Word16 original_subframes_rendered, original_slots_rendered; Word32 tmpInputBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k]; diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 8ec066dc9..f430f073d 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -113,7 +113,7 @@ static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBIN static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME] /*q_inp*/[CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 decIm[] /*q_inp*/[CLDFB_NO_CHANNELS_MAX] ); #ifdef SPLIT_REND_WITH_HEAD_ROT -static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 subframe, Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, Word32 *IIReneLimiter, Word16 q ); +static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 subframe, Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, Word32 *IIReneLimiter, Word16 q ); static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 Rmat[3][3], const Word16 subframe, const Word16 isHeadtracked, const Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, const Word32 *IIReneLimiter, const MASA_ISM_DATA_HANDLE hMasaIsmData ); #else @@ -1343,12 +1343,11 @@ static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( Word16 q ) { Word16 ch, slot, bin; - Word16 nBins, shift; + Word16 nBins; Word32 IIReneLimiterFactor_fx; // Q26 Word32 qualityBasedSmFactor_fx; Word32 lowBitRateEQ_fx[CLDFB_NO_CHANNELS_MAX]; UWord8 applyLowBitRateEQ; - PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE]; IVAS_FORMAT ivas_format; Word32 ivas_total_brate; Word16 nchan_transport; @@ -1598,9 +1597,9 @@ static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( Word32 Rmat_fx[3][3], const int16_t subframe, const int16_t isHeadtracked, - Word32 *subFrameTotalEne_fx, + const Word32 *subFrameTotalEne_fx, Word16 *subFrameTotalEne_e, - Word32 *IIReneLimiter_fx, + const Word32 *IIReneLimiter_fx, const MASA_ISM_DATA_HANDLE hMasaIsmData ) { Word16 ch, bin; @@ -1655,6 +1654,8 @@ static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( move16(); } + dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe]; + /* Determine target covariance matrix containing target binaural properties */ FOR( bin = 0; bin < nBins; bin++ ) { @@ -3398,7 +3399,7 @@ static void ivas_dirac_dec_binaural_process_output_fx( Word32 reverbIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], - const UWord8 recompute + const Word8 recompute #endif ) { @@ -6529,8 +6530,11 @@ static void ivas_masa_ext_rend_parambin_internal_fx( } } Word32 Rmat_fx[3][3]; - +#ifdef SPLIT_REND_WITH_HEAD_ROT + hDiracDecBin = hMasaExtRend->hDiracDecBin[0]; +#else hDiracDecBin = hMasaExtRend->hDiracDecBin; +#endif assert( hDiracDecBin ); hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom; nBins = hSpatParamRendCom->num_freq_bands; @@ -6768,9 +6772,9 @@ static void ivas_masa_ext_rend_parambin_internal_fx( assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" ); /* re-use input covariance for the side renderings */ - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - mvr2r( hMasaExtRend->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands ); + Copy32( hMasaExtRend->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands ); } Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands ); Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands ); diff --git a/lib_rend/ivas_orient_trk.c b/lib_rend/ivas_orient_trk.c index a3e833455..acd1621d6 100644 --- a/lib_rend/ivas_orient_trk.c +++ b/lib_rend/ivas_orient_trk.c @@ -34,6 +34,7 @@ #include #include "options.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_prot_rend.h" #include "ivas_cnst.h" #include @@ -696,11 +697,20 @@ ivas_error ivas_orient_trk_SetReferenceRotation_fx( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* check for Euler angle signaling */ + IF( EQ_32( refRot.w_fx, L_negate( 12582912 ) ) && EQ_16( refRot.q_fact, Q22 ) ) + { + Euler2Quat_fx( deg2rad_fx( refRot.x_fx ), deg2rad_fx( refRot.y_fx ), deg2rad_fx( refRot.z_fx ), &pOTR->refRot ); + modify_Quat_q_fx( &pOTR->refRot, &pOTR->refRot, Q29 ); + } +#else /* check for Euler angle signaling */ IF( EQ_32( refRot.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) { Euler2Quat_fx( deg2rad_fx( refRot.x_fx ), deg2rad_fx( refRot.y_fx ), deg2rad_fx( refRot.z_fx ), &pOTR->refRot ); } +#endif pOTR->refRot = refRot; return IVAS_ERR_OK; diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index f20cab785..b27c0cd15 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -378,10 +378,10 @@ Word16 ivas_get_nchan_buffers_dec( { nchan_out_buff = s_max( nchan_out_buff, add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ); } - ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + else if ( EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || - EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || + EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) #endif ) { diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 51fca0ec8..9a4a1a279 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1618,14 +1618,6 @@ void QuatToRotMat( float Rmat[3][3] /* o : real-space rotation matrix for this rotation */ ); -#ifdef SPLIT_REND_WITH_HEAD_ROT -void Quat2EulerDegree( - const IVAS_QUATERNION quat, /* i : quaternion describing the rotation */ - float *yaw, /* o : yaw */ - float *pitch, /* o : pitch */ - float *roll /* o : roll */ -); -#endif void rotateAziEle( float azi_in, /* i : output elevation */ @@ -2049,7 +2041,7 @@ void ivas_rend_CldfbMultiBinRendProcess( Word32 Cldfb_Out_Imag[MAX_HEAD_ROT_POSES*BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const Word16 low_res_pre_rend_rot, const Word16 num_subframes, - Word16 *Q_in + const Word16 Q_in ); ivas_error ivas_rend_openCldfb( diff --git a/lib_rend/ivas_reflections.c b/lib_rend/ivas_reflections.c index c5d118858..c7d9c74e5 100644 --- a/lib_rend/ivas_reflections.c +++ b/lib_rend/ivas_reflections.c @@ -40,6 +40,7 @@ #include "ivas_stat_rend.h" #include "ivas_cnst.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_rom_com.h" #include "wmc_auto.h" #include "prot_fx.h" @@ -340,10 +341,17 @@ ivas_error ivas_er_encoder_init( p_y_fx = reflections->shoebox_data.az_angle.data_fx[i]; // Q23 move32(); move32(); - - rad_el_angle = deg2rad_fx( p_x_fx ); // Q23 - rad_az_angle = deg2rad_fx( p_y_fx ); // Q23 - +#ifdef SPLIT_REND_WITH_HEAD_ROT + p_x_fx = L_shr( p_x_fx, 1 ); // Q22 + p_y_fx = L_shr( p_y_fx, 1 ); // Q22 +#endif + rad_el_angle = deg2rad_fx( p_x_fx ); // Q22 + rad_az_angle = deg2rad_fx( p_y_fx ); // Q22 + +#ifdef SPLIT_REND_WITH_HEAD_ROT + rad_el_angle = L_shl( rad_el_angle, 1 ); // Q23 + rad_az_angle = L_shl( rad_az_angle, 1 ); // Q23 +#endif rad_el_angle = L_shr( rad_el_angle, 10 ); // Q13 rad_az_angle = L_shr( rad_az_angle, 10 ); // Q13 diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index 8651de7f7..f307e29f5 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -733,7 +733,7 @@ void rotateFrame_shd( /* calculate ambisonics rotation matrices for the previous and current frames */ #ifdef SPLIT_REND_WITH_HEAD_ROT - SHrotmatgen( SHrotmat_prev, hCombinedOrientationData->Rmat_prev_fx[0], shd_rot_max_order ); + SHrotmatgen_fx( SHrotmat_prev, hCombinedOrientationData->Rmat_prev_fx[0], shd_rot_max_order ); #else SHrotmatgen_fx( SHrotmat_prev, hCombinedOrientationData->Rmat_prev_fx, shd_rot_max_order ); #endif @@ -795,7 +795,7 @@ void rotateFrame_shd( /* move Rmat to Rmat_prev */ FOR( i = 0; i < 3; i++ ) { - MVR2R_WORD32( + Copy32( hCombinedOrientationData->Rmat_fx[subframe_idx][i], #ifdef SPLIT_REND_WITH_HEAD_ROT hCombinedOrientationData->Rmat_prev_fx[0][i], @@ -996,7 +996,7 @@ void rotateFrame_sd( /* move Rmat to Rmat_prev */ FOR( i = 0; i < 3; i++ ) { - MVR2R_WORD32( + Copy32( hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i], // Q30 #ifdef SPLIT_REND_WITH_HEAD_ROT hCombinedOrientationData->Rmat_prev_fx[0][i], @@ -1008,7 +1008,7 @@ void rotateFrame_sd( /* copy to output */ FOR( ch_out = 0; ch_out < nchan; ch_out++ ) { - MVR2R_WORD32( &output_tmp_fx[ch_out][offset], &output[ch_out][offset], subframe_len ); // Q11 + Copy32( &output_tmp_fx[ch_out][offset], &output[ch_out][offset], subframe_len ); // Q11 } pop_wmops(); @@ -2461,11 +2461,11 @@ void ivas_combined_orientation_update_index( Word16 exp, div_result; IF( hCombinedOrientationData != NULL ) { - IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) #ifdef SPLIT_REND_WITH_HEAD_ROT - || hCombinedOrientationData->sr_low_res_flag + IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) || hCombinedOrientationData->sr_low_res_flag ) +#else + IF( EQ_16( hCombinedOrientationData->num_subframes, 1 ) ) #endif - ) { /* only one orientation available anyway or split rendering with low resolution*/ hCombinedOrientationData->subframe_idx = 0; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index b33ce2942..448375dfd 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -4546,7 +4546,7 @@ ivas_error IVAS_REND_FeedInputAudio_fx( IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && - shr( i_mult( inputAudio.config.numSamplesPerChannel, 1000 ), cldfb2tdShift ) != i_mult( i_mult( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) + NE_32( L_shr( L_mult0( inputAudio.config.numSamplesPerChannel, 1000 ), cldfb2tdShift ), (Word32) W_mult0_32_32( L_mult0( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) ) #else IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && NE_32( L_mult0( inputAudio.config.numSamplesPerChannel, 1000 ), (Word32) W_mult0_32_32( L_mult0( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) ) @@ -6250,6 +6250,7 @@ static ivas_error renderIsmToSplitBinaural( { ivas_error error; Word32 tmpProcessing[MAX_NUM_OBJECTS][L_FRAME48k]; + Word32 *pTmpProcessing[MAX_NUM_OBJECTS]; Word16 pos_idx; const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; const SPLIT_REND_WRAPPER *pSplitRendWrapper; @@ -6258,13 +6259,14 @@ static ivas_error renderIsmToSplitBinaural( Word32 tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; Word16 output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; - Word16 ism_md_subframe_update_ext; + Word16 ism_md_subframe_update_ext, exp; push_wmops( "renderIsmToSplitBinaural" ); pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper; pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; + exp = *outAudio.pq_fact; /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */ ism_md_subframe_update_ext = (Word16) Mpy_32_32( ismInput->ism_metadata_delay_ms_fx, ONE_BY_SUBFRAME_LEN_MS_Q31 ); @@ -6287,6 +6289,12 @@ static ivas_error renderIsmToSplitBinaural( /* Copy input audio to a processing buffer. */ copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing ); + FOR( i = 0; i < MAX_NUM_OBJECTS; i++ ) + { + pTmpProcessing[i] = tmpProcessing[i]; + } + + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { /* Update head positions */ @@ -6315,13 +6323,33 @@ static ivas_error renderIsmToSplitBinaural( } } + + FOR( i = 0; i < MAX_NUM_OBJECTS; ++i ) + { + Scale_sig32( tmpProcessing[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */ + } /* Render */ - IF( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[sub( pos_idx, 1 )], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, - NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_ext_fx( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[sub( pos_idx, 1 )], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, + NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing, &exp ) ) != IVAS_ERR_OK ) { return error; } + FOR( i = 0; i < BINAURAL_CHANNELS; ++i ) + { + Scale_sig32( tmpProcessing[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */ + } + IF( ismInput->hReverb != NULL ) + { + FOR( i = 0; i < BINAURAL_CHANNELS; i++ ) + { + FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel; j++ ) + { + tmpProcessing[i][j] = L_shl( tmpProcessing[i][j], Q2 ); /* Q(exp + 2) */ + move32(); + } + } + } /* Copy rendered audio to tmp storage buffer. Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ Copy32( tmpProcessing[0], tmpBinaural[i_mult( 2, pos_idx )], output_frame ); @@ -6612,7 +6640,7 @@ static ivas_error renderLfeToBinaural_fx( IF( mcInput->base.ctx.pSplitRendWrapper != NULL ) { num_poses = mcInput->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses; - Move16(); + move16(); } ELSE { @@ -6854,14 +6882,17 @@ static ivas_error renderMcToBinauralRoom( tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); set32_fx( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); - IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, #ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx[0], + mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), + IVAS_ERR_OK ) ) #else + IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx, -#endif mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -6966,14 +6997,17 @@ static ivas_error renderMcCustomLsToBinauralRoom( tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); set32_fx( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels ); - IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, #ifdef SPLIT_REND_WITH_HEAD_ROT + IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx[0], + mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), + IVAS_ERR_OK ) ) #else + IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx, -#endif mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -7222,11 +7256,19 @@ static ivas_error renderMcToSplitBinaural( /* perform rotation in source format to tmpRotBuffer */ pCombinedOrientationDataLocal = &combinedOrientationDataLocal; + FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i ) + { + Scale_sig32( tmpRendBuffer[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */ + } /* Render */ - IF( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &mcInput->tdRendWrapper : &mcInput->splitTdRendWrappers[pos_idx - 1], mcInput->base.inConfig, &mcInput->customLsInput, &pCombinedOrientationDataLocal, NULL, mcInput->hReverb, 0, /* Ism Audio Metadata Delay Sync in ms for External Renderer */ *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer ) ) != IVAS_ERR_OK ) + IF( ( error = ivas_td_binaural_renderer_ext_fx( ( pos_idx == 0 ) ? &mcInput->tdRendWrapper : &mcInput->splitTdRendWrappers[pos_idx - 1], mcInput->base.inConfig, &mcInput->customLsInput, &pCombinedOrientationDataLocal, NULL, mcInput->hReverb, 0, /* Ism Audio Metadata Delay Sync in ms for External Renderer */ *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer, &exp ) ) != IVAS_ERR_OK ) { return error; } + FOR( i = 0; i < BINAURAL_CHANNELS; ++i ) + { + Scale_sig32( tmpRendBuffer[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */ + } /* Copy rendered audio to tmp storage buffer. Copying directly to output would * overwrite original audio, which is still needed for rendering next head pose. */ @@ -7569,7 +7611,7 @@ static ivas_error renderSbaToMultiBinauralCldfb( copyBufferToCLDFBarray_fx( sbaInput->base.inputBuffer, Cldfb_RealBuffer, Cldfb_ImagBuffer ); ivas_rend_CldfbMultiBinRendProcess( sbaInput->cldfbRendWrapper.hCldfbRend, sbaInput->base.ctx.pCombinedOrientationData, &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData, - Cldfb_RealBuffer, Cldfb_ImagBuffer, Cldfb_Out_Real, Cldfb_Out_Imag, low_res_pre_rend_rot, num_subframes, &Q_in ); + Cldfb_RealBuffer, Cldfb_ImagBuffer, Cldfb_Out_Real, Cldfb_Out_Imag, low_res_pre_rend_rot, num_subframes, Q_in ); return IVAS_ERR_OK; } @@ -7805,15 +7847,19 @@ static ivas_error renderSbaToBinauralRoom( /* copy input for in-place rotation */ Copy32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, i_mult( tmpRotBuffer.config.numChannels, tmpRotBuffer.config.numSamplesPerChannel ) ); +#ifdef SPLIT_REND_WITH_HEAD_ROT IF( NE_32( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->base.ctx.pCombinedOrientationData, -#ifdef SPLIT_REND_WITH_HEAD_ROT sbaInput->rot_gains_prev_fx[0], + tmpRotBuffer ) ), + IVAS_ERR_OK ) ) #else + IF( NE_32( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, + sbaInput->base.ctx.pCombinedOrientationData, sbaInput->rot_gains_prev_fx, -#endif tmpRotBuffer ) ), IVAS_ERR_OK ) ) +#endif { return error; } @@ -7909,7 +7955,7 @@ static ivas_error renderInputSba( #ifdef SPLIT_REND_WITH_HEAD_ROT cldfb2tdShift = outAudio.config.is_cldfb ? 1 : 0; - IF( NE_16( shl( sbaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) && + IF( NE_32( L_shl( sbaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) #else IF( NE_32( sbaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) @@ -8290,7 +8336,7 @@ static ivas_error renderInputMasa( #ifdef SPLIT_REND_WITH_HEAD_ROT cldfb2tdShift = outAudio.config.is_cldfb ? 1 : 0; - IF( ( NE_16( shl( masaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) ) && + IF( ( NE_32( L_shl( masaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) #else IF( NE_32( masaInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) ) @@ -8972,7 +9018,7 @@ static ivas_error getSamplesInternal( IF( NE_16( pcm_out_flag, 0 ) ) { - accumulate2dArrayToBuffer( tmpBinaural_buff, &outAudio ); + accumulate2dArrayToBuffer_fx( tmpBinaural_buff, &outAudio ); } } #endif @@ -9156,7 +9202,7 @@ IVAS_REND_openCldfb( for ( n = 0; n < num_in_chs; n++ ) { - if ( ( error = openCldfb( &( cldfbAna[n] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + if ( ( error = openCldfb_ivas_fx( &( cldfbAna[n] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) { return error; } @@ -9168,7 +9214,7 @@ IVAS_REND_openCldfb( for ( n = 0; n < num_out_chs; n++ ) { - if ( ( error = openCldfb( &( cldfbSyn[n] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) + if ( ( error = openCldfb_ivas_fx( &( cldfbSyn[n] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS ) ) != IVAS_ERR_OK ) { return error; } @@ -9222,15 +9268,14 @@ void IVAS_REND_closeCldfb( *-------------------------------------------------------------------*/ void IVAS_REND_cldfbAnalysis_ts_wrapper( - const float *timeIn, /* i : time buffer */ - float realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ - float imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ - const int16_t samplesToProcess, /* i : samples to process */ - IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filterbank state */ + const Word32 *timeIn, /* i : time buffer */ + Word32 realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ + Word32 imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ + const Word16 samplesToProcess, /* i : samples to process */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filterbank state */ Word16 Q_in, Word16 *Q_out ) { - cldfbAnalysis_ts( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb ); Word16 Q_cldfb = Q_in; cldfbAnalysis_ts_fx_fixed_q( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb, diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 59f0ea4dd..6d7ce0bdf 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -386,11 +386,11 @@ void IVAS_REND_closeCldfb( ); void IVAS_REND_cldfbAnalysis_ts_wrapper( - const float *timeIn, /* i : time buffer */ - float realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ - float imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ - const int16_t samplesToProcess, /* i : samples to process */ - IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filterbank state */ + const Word32 *timeIn, /* i : time buffer */ + Word32 realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : real value buffer */ + Word32 imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o : imag value buffer */ + const Word16 samplesToProcess, /* i : samples to process */ + IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filterbank state */ Word16 Q_in, Word16 *Q_out ); diff --git a/lib_util/rotation_file_reader.c b/lib_util/rotation_file_reader.c index 987d40c85..b13d99045 100644 --- a/lib_util/rotation_file_reader.c +++ b/lib_util/rotation_file_reader.c @@ -121,15 +121,32 @@ ivas_error HeadRotationFileReading( ( headRotReader->frameCounter )++; - pQuaternion->w = w; - pQuaternion->x = x; - pQuaternion->y = y; - pQuaternion->z = z; + +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( w == -3.0f ) + { + pQuaternion->w_fx = floatToFixed_32( w, Q22 ); + pQuaternion->x_fx = floatToFixed_32( x, Q22 ); + pQuaternion->y_fx = floatToFixed_32( y, Q22 ); + pQuaternion->z_fx = floatToFixed_32( z, Q22 ); + pQuaternion->q_fact = Q22; + } + else + { + pQuaternion->w_fx = floatToFixed_32( w, Q31 ); + pQuaternion->x_fx = floatToFixed_32( x, Q31 ); + pQuaternion->y_fx = floatToFixed_32( y, Q31 ); + pQuaternion->z_fx = floatToFixed_32( z, Q31 ); + pQuaternion->q_fact = Q31; + } +#else pQuaternion->w_fx = floatToFixed_32( w, Q31 ); pQuaternion->x_fx = floatToFixed_32( x, Q31 ); pQuaternion->y_fx = floatToFixed_32( y, Q31 ); pQuaternion->z_fx = floatToFixed_32( z, Q31 ); pQuaternion->q_fact = Q31; +#endif + if ( pPos != NULL ) { pPos->x = posx; -- GitLab From cb925aad93a92bd6fa2edc45b8820b3afa8bef14 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 12:37:25 +1100 Subject: [PATCH 10/43] windows compilation fixes, temp fix in wmc_auto.h --- apps/isar_post_rend.c | 2 +- apps/renderer.c | 22 +- lib_com/ivas_limiter.c | 1 + lib_com/ivas_prot.h | 16 +- lib_com/ivas_rom_com.c | 819 +++++++++++++++++++ lib_com/ivas_rom_com.h | 3 + lib_com/lsf_tools_fx.c | 4 +- lib_debug/wmc_auto.h | 56 +- lib_dec/ivas_init_dec.c | 2 +- lib_isar/isar_prot.h | 14 - lib_isar/isar_splitRenderer_utils.c | 111 --- lib_lc3plus/defines.h | 26 + lib_rend/ivas_dirac_dec_binaural_functions.c | 4 +- lib_rend/ivas_rom_rend.c | 817 ------------------ lib_rend/ivas_rom_rend.h | 2 - lib_rend/lib_rend.c | 10 +- lib_rend/lib_rend.h | 2 +- 17 files changed, 914 insertions(+), 997 deletions(-) diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c index c28a5b811..278503690 100644 --- a/apps/isar_post_rend.c +++ b/apps/isar_post_rend.c @@ -1047,7 +1047,7 @@ int main( IVAS_QUATERNION headRot; IVAS_VECTOR3 Pos; - IF( ( error = HeadRotationFileReading_fx( headRotReader, &headRot, &Pos ) ) != IVAS_ERR_OK ) + IF( ( error = HeadRotationFileReading( headRotReader, &headRot, &Pos ) ) != IVAS_ERR_OK ) { fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); exit( -1 ); diff --git a/apps/renderer.c b/apps/renderer.c index 09b1425ce..a41b633e2 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1373,7 +1373,7 @@ int main( #endif ); - if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) + if ( IVAS_REND_GetDelay_fx( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to get delay of renderer!\n" ); exit( -1 ); @@ -1414,7 +1414,7 @@ int main( #endif ); - if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) + if ( IVAS_REND_GetDelay_fx( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to get delay of renderer!\n" ); exit( -1 ); @@ -1576,7 +1576,7 @@ int main( #ifdef SPLIT_REND_WITH_HEAD_ROT Word16 Q_out; *outBuffer.pq_fact = 16 - ( gd_bits ); - convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, inBuffer.config.is_cldfb, cldfbAna, *outBuffer.pq_fact, &Q_out ); + convertInputBuffer_fx( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inInt32Buffer, *outBuffer.pq_fact, inBuffer.config.is_cldfb, cldfbAna, &Q_out ); *outBuffer.pq_fact = Q_out; #else *outBuffer.pq_fact = 16 - ( gd_bits ); @@ -3854,7 +3854,7 @@ static void convertInputBuffer_fx( IVAS_REND_cldfbAnalysis_ts_wrapper( &fIn[chnl][numCldfbBands * slotIdx], &Word32Buffer[( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], &Word32Buffer[numCldfbBands + ( chnl * numFloatSamplesPerChannel ) + ( 2 * slotIdx * numCldfbBands )], - numCldfbBands, cldfbAna[chnl], Q11, *out_q_factor ); + numCldfbBands, cldfbAna[chnl], Q11, out_q_factor ); } } } @@ -3916,7 +3916,7 @@ static void convertOutputBuffer_fx( #ifdef SPLIT_REND_WITH_HEAD_ROT IF( cldfb_in_flag ) { - Word16 slotIdx, numCldfbBands, numPcmSamples, b, temp_out_q; + Word16 slotIdx, numCldfbBands, numPcmSamples, b, temp_out_q = 0; Word32 fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; Word32 re[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; Word32 im[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; @@ -3960,7 +3960,17 @@ static void convertOutputBuffer_fx( { FOR( chnl = 0; chnl < numChannels; ++chnl ) { - intBuffer[i] = (Word16) L_shl( fIn[chnl][smpl], sub( out_q, temp_out_q ) ); + temp_fx = L_add( fIn[chnl][smpl], lshl( 1, ( temp_out_q - 1 ) ) ); + temp_fx1 = L_shr( temp_fx, temp_out_q ); + IF( GT_32( temp_fx1, IVAS_MAX16B_FX ) ) + { + temp_fx1 = IVAS_MAX16B_FX; + } + ELSE IF( LT_32( temp_fx1, IVAS_MIN16B_FX ) ) + { + temp_fx1 = IVAS_MIN16B_FX; + } + intBuffer[i] = (Word16) temp_fx1; ++i; } } diff --git a/lib_com/ivas_limiter.c b/lib_com/ivas_limiter.c index 17211d1c6..e0ec108a5 100644 --- a/lib_com/ivas_limiter.c +++ b/lib_com/ivas_limiter.c @@ -36,6 +36,7 @@ #include "prot.h" #include "ivas_prot_rend.h" #include "ivas_rom_rend.h" +#include "ivas_rom_com.h" #include "wmc_auto.h" #include #include "ivas_prot_fx.h" diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index e7827023b..d99f58db1 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3296,26 +3296,26 @@ void ivas_td_decorr_get_ducking_gains( ); #define IVAS_CMULT_FLOAT( in1_re, in1_im, in2_re, in2_im, out1_re, out1_im ) \ - out1_re = ( in1_re * in2_re ) - ( in1_im * in2_im ); MAC(1); MULT(1); \ - out1_im = ( in1_re * in2_im ) + ( in2_re * in1_im ); MAC(1); MULT(1); + out1_re = ( in1_re * in2_re ) - ( in1_im * in2_im ); \ + out1_im = ( in1_re * in2_im ) + ( in2_re * in1_im ); #define IVAS_CALCULATE_ABS( re, im, out ) \ - out = sqrtf( ( re * re ) + ( im * im ) ); MAC(1); MULT(1); SQRT(1); + out = sqrtf( ( re * re ) + ( im * im ) ); #define IVAS_CALCULATE_RABS( re, out ) \ - out = sqrtf( re * re ); MULT(1); SQRT(1); + out = sqrtf( re * re ); #define IVAS_CALCULATE_SQ_ABS( re, im, out ) \ - out = (float) ( ( re * re ) + ( im * im ) ); MAC(1); MULT(1); + out = (float) ( ( re * re ) + ( im * im ) ); #define IVAS_RMULT_DOUBLE( in1_re, in2_re, out1_re ) \ - out1_re = ( in1_re * in2_re ); DMULT(1); \ + out1_re = ( in1_re * in2_re ); \ #define IVAS_CALCULATE_SQ_ABS_N( re, out ) \ - out = (float) ( re * re ); MULT(1); + out = (float) ( re * re ); #define IVAS_RMULT_FLOAT( in1_re, in2_re, out1_re ) \ - out1_re = ( in1_re * in2_re ); MULT(1); + out1_re = ( in1_re * in2_re ); /* PCA */ diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 5a864835c..6023812c8 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -2901,3 +2901,822 @@ const Word16 ivas_param_upmx_mx_qmap[33] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + +const Word32 release_cnst_table[4][201] = // Q31 + { + { + 1913946752, + 1919716352, + 1925351680, + 1930855552, + 1936230784, + 1941479808, + 1946605312, + 1951609728, + 1956495744, + 1961265792, + 1965922304, + 1970467584, + 1974904320, + 1979234560, + 1983460736, + 1987585024, + 1991609856, + 1995537280, + 1999369344, + 2003108480, + 2006756480, + 2010315520, + 2013787520, + 2017174528, + 2020478464, + 2023701248, + 2026844672, + 2029910656, + 2032900992, + 2035817344, + 2038661376, + 2041435008, + 2044139648, + 2046777088, + 2049348864, + 2051856384, + 2054301440, + 2056685312, + 2059009536, + 2061275520, + 2063484672, + 2065638272, + 2067737856, + 2069784448, + 2071779584, + 2073724416, + 2075620096, + 2077467904, + 2079268992, + 2081024512, + 2082735488, + 2084403200, + 2086028416, + 2087612544, + 2089156352, + 2090660864, + 2092127104, + 2093555968, + 2094948480, + 2096305408, + 2097627776, + 2098916352, + 2100172032, + 2101395584, + 2102587776, + 2103749504, + 2104881408, + 2105984384, + 2107059072, + 2108106112, + 2109126400, + 2110120448, + 2111088896, + 2112032512, + 2112951808, + 2113847552, + 2114720128, + 2115570304, + 2116398592, + 2117205504, + 2117991552, + 2118757504, + 2119503616, + 2120230400, + 2120938496, + 2121628288, + 2122300288, + 2122954880, + 2123592576, + 2124213760, + 2124818944, + 2125408384, + 2125982592, + 2126541952, + 2127086848, + 2127617664, + 2128134656, + 2128638336, + 2129128832, + 2129606784, + 2130072192, + 2130525568, + 2130967296, + 2131397376, + 2131816448, + 2132224640, + 2132622080, + 2133009408, + 2133386496, + 2133753856, + 2134111744, + 2134460288, + 2134799744, + 2135130368, + 2135452416, + 2135766144, + 2136071680, + 2136369152, + 2136659072, + 2136941312, + 2137216256, + 2137484160, + 2137744896, + 2137998976, + 2138246400, + 2138487424, + 2138722176, + 2138950656, + 2139173376, + 2139390208, + 2139601408, + 2139807104, + 2140007424, + 2140202624, + 2140392576, + 2140577664, + 2140758016, + 2140933504, + 2141104512, + 2141271040, + 2141433216, + 2141591168, + 2141745024, + 2141894912, + 2142040832, + 2142182912, + 2142321408, + 2142456192, + 2142587392, + 2142715264, + 2142839808, + 2142961152, + 2143079296, + 2143194240, + 2143306240, + 2143415424, + 2143521664, + 2143625216, + 2143725952, + 2143824128, + 2143919744, + 2144012800, + 2144103424, + 2144191744, + 2144277760, + 2144361472, + 2144443136, + 2144522496, + 2144599936, + 2144675200, + 2144748544, + 2144820096, + 2144889600, + 2144957440, + 2145023488, + 2145087744, + 2145150336, + 2145211264, + 2145270656, + 2145328512, + 2145384832, + 2145439616, + 2145493120, + 2145545088, + 2145595776, + 2145645056, + 2145693184, + 2145739904, + 2145785472, + 2145829888, + 2145873152, + 2145915136, + 2145956224, + 2145996032, + 2146034944, + 2146072832, + 2146109696, + 2146145664, + 2146180608, + 2146214656, + 2146247808, + }, + { + 2027355264, + 2030408704, + 2033386624, + 2036290944, + 2039123328, + 2041885440, + 2044578944, + 2047205376, + 2049766528, + 2052263680, + 2054698496, + 2057072384, + 2059387008, + 2061643520, + 2063843328, + 2065987968, + 2068078720, + 2070116864, + 2072103552, + 2074040192, + 2075927936, + 2077767936, + 2079561472, + 2081309568, + 2083013376, + 2084673920, + 2086292352, + 2087869696, + 2089406976, + 2090905216, + 2092365184, + 2093788032, + 2095174528, + 2096525824, + 2097842432, + 2099125632, + 2100375808, + 2101594240, + 2102781312, + 2103938048, + 2105065216, + 2106163456, + 2107233536, + 2108276096, + 2109292032, + 2110281728, + 2111246080, + 2112185728, + 2113101056, + 2113992960, + 2114861824, + 2115708288, + 2116532992, + 2117336448, + 2118119168, + 2118881792, + 2119624704, + 2120348416, + 2121053440, + 2121740288, + 2122409344, + 2123061120, + 2123696128, + 2124314624, + 2124917120, + 2125504128, + 2126075776, + 2126632832, + 2127175296, + 2127703808, + 2128218624, + 2128720000, + 2129208448, + 2129684352, + 2130147712, + 2130599168, + 2131038976, + 2131467264, + 2131884416, + 2132290816, + 2132686592, + 2133072256, + 2133447680, + 2133813504, + 2134169856, + 2134516864, + 2134854784, + 2135184000, + 2135504640, + 2135816960, + 2136121216, + 2136417536, + 2136706048, + 2136987136, + 2137260928, + 2137527552, + 2137787264, + 2138040192, + 2138286592, + 2138526464, + 2138760192, + 2138987776, + 2139209472, + 2139425408, + 2139635712, + 2139840512, + 2140039936, + 2140234240, + 2140423424, + 2140607744, + 2140787200, + 2140962048, + 2141132288, + 2141298048, + 2141459584, + 2141616896, + 2141769984, + 2141919232, + 2142064512, + 2142205952, + 2142343808, + 2142478080, + 2142608768, + 2142736128, + 2142860032, + 2142980864, + 2143098368, + 2143212928, + 2143324544, + 2143433088, + 2143538944, + 2143641984, + 2143742336, + 2143840000, + 2143935232, + 2144027904, + 2144118144, + 2144206080, + 2144291712, + 2144375168, + 2144456320, + 2144535424, + 2144612480, + 2144687488, + 2144760448, + 2144831616, + 2144900992, + 2144968448, + 2145034112, + 2145098112, + 2145160448, + 2145221248, + 2145280256, + 2145337856, + 2145393920, + 2145448576, + 2145501696, + 2145553536, + 2145603968, + 2145653120, + 2145700992, + 2145747456, + 2145792896, + 2145837056, + 2145880064, + 2145922048, + 2145962880, + 2146002560, + 2146041344, + 2146078976, + 2146115712, + 2146151424, + 2146186240, + 2146220160, + 2146253184, + 2146285312, + 2146316672, + 2146347136, + 2146376832, + 2146405760, + 2146433920, + 2146461440, + 2146488192, + 2146514176, + 2146539520, + 2146564224, + 2146588160, + 2146611584, + 2146634368, + 2146656640, + 2146678272, + 2146699264, + 2146719744, + 2146739712, + 2146759168, + 2146778112, + 2146796544, + 2146814464, + 2146832000, + 2146849024, + 2146865664, + }, + { + 2086555136, + 2088125824, + 2089656576, + 2091148416, + 2092602240, + 2094018944, + 2095399680, + 2096745088, + 2098056192, + 2099333888, + 2100578816, + 2101792000, + 2102974080, + 2104125824, + 2105248128, + 2106341760, + 2107407232, + 2108445440, + 2109456896, + 2110442496, + 2111402624, + 2112338176, + 2113249664, + 2114137728, + 2115002880, + 2115845760, + 2116666880, + 2117466880, + 2118246272, + 2119005568, + 2119745280, + 2120465920, + 2121167872, + 2121851776, + 2122517888, + 2123166976, + 2123799168, + 2124414976, + 2125014912, + 2125599360, + 2126168704, + 2126723200, + 2127263360, + 2127789568, + 2128302208, + 2128801408, + 2129287808, + 2129761536, + 2130222976, + 2130672512, + 2131110272, + 2131536768, + 2131952128, + 2132356736, + 2132750848, + 2133134720, + 2133508736, + 2133872896, + 2134227584, + 2134573184, + 2134909696, + 2135237504, + 2135556736, + 2135867648, + 2136170624, + 2136465536, + 2136752896, + 2137032832, + 2137305344, + 2137570816, + 2137829376, + 2138081280, + 2138326528, + 2138565504, + 2138798080, + 2139024768, + 2139245440, + 2139460480, + 2139669888, + 2139873792, + 2140072320, + 2140265856, + 2140454144, + 2140637696, + 2140816384, + 2140990464, + 2141159936, + 2141325056, + 2141485824, + 2141642368, + 2141794944, + 2141943424, + 2142088064, + 2142228992, + 2142366208, + 2142499840, + 2142630016, + 2142756736, + 2142880128, + 2143000448, + 2143117440, + 2143231488, + 2143342592, + 2143450752, + 2143556096, + 2143658624, + 2143758592, + 2143855872, + 2143950592, + 2144043008, + 2144132864, + 2144220416, + 2144305664, + 2144388608, + 2144469504, + 2144548224, + 2144624896, + 2144699648, + 2144772352, + 2144843264, + 2144912256, + 2144979328, + 2145044864, + 2145108480, + 2145170560, + 2145231104, + 2145289856, + 2145347200, + 2145403008, + 2145457408, + 2145510400, + 2145561984, + 2145612160, + 2145661056, + 2145708672, + 2145755136, + 2145800192, + 2145844224, + 2145887104, + 2145928832, + 2145969408, + 2146008960, + 2146047616, + 2146085120, + 2146121600, + 2146157184, + 2146191872, + 2146225664, + 2146258560, + 2146290560, + 2146321792, + 2146352128, + 2146381696, + 2146410496, + 2146438528, + 2146465920, + 2146492416, + 2146518400, + 2146543616, + 2146568192, + 2146592128, + 2146615424, + 2146638080, + 2146660224, + 2146681728, + 2146702720, + 2146723072, + 2146743040, + 2146762368, + 2146781184, + 2146799616, + 2146817408, + 2146834816, + 2146851840, + 2146868352, + 2146884352, + 2146900096, + 2146915328, + 2146930176, + 2146944640, + 2146958720, + 2146972416, + 2146985856, + 2146998784, + 2147011456, + 2147023872, + 2147035904, + 2147047552, + 2147058944, + 2147070080, + 2147080832, + 2147091456, + 2147101696, + 2147111680, + 2147121408, + 2147130880, + 2147140096, + 2147149056, + 2147157760, + 2147166336, + 2147174656, + }, + { + 2106670080, + 2107727232, + 2108757120, + 2109760640, + 2110738432, + 2111691008, + 2112619136, + 2113523328, + 2114404352, + 2115262592, + 2116098816, + 2116913408, + 2117707136, + 2118480256, + 2119233536, + 2119967360, + 2120682240, + 2121378688, + 2122057088, + 2122717952, + 2123361792, + 2123988992, + 2124599936, + 2125195136, + 2125774848, + 2126339584, + 2126889728, + 2127425536, + 2127947520, + 2128456064, + 2128951296, + 2129433856, + 2129903744, + 2130361600, + 2130807424, + 2131241728, + 2131664768, + 2132076928, + 2132478208, + 2132869248, + 2133250048, + 2133620992, + 2133982208, + 2134334080, + 2134676864, + 2135010688, + 2135335936, + 2135652608, + 2135961088, + 2136261504, + 2136554112, + 2136839168, + 2137116800, + 2137387136, + 2137650560, + 2137907072, + 2138156928, + 2138400256, + 2138637184, + 2138867968, + 2139092864, + 2139311744, + 2139524992, + 2139732736, + 2139934976, + 2140131968, + 2140323840, + 2140510720, + 2140692736, + 2140870016, + 2141042688, + 2141210752, + 2141374592, + 2141534080, + 2141689344, + 2141840640, + 2141987968, + 2142131456, + 2142271232, + 2142407424, + 2142539904, + 2142669056, + 2142794752, + 2142917248, + 2143036544, + 2143152640, + 2143265792, + 2143375872, + 2143483264, + 2143587712, + 2143689472, + 2143788544, + 2143885056, + 2143979136, + 2144070656, + 2144159872, + 2144246656, + 2144331264, + 2144413568, + 2144493824, + 2144571904, + 2144647936, + 2144722048, + 2144794240, + 2144864512, + 2144932864, + 2144999552, + 2145064448, + 2145127680, + 2145189248, + 2145249152, + 2145307520, + 2145364480, + 2145419776, + 2145473792, + 2145526272, + 2145577472, + 2145627264, + 2145675776, + 2145723008, + 2145768960, + 2145813760, + 2145857408, + 2145899904, + 2145941376, + 2145981696, + 2146020864, + 2146059136, + 2146096384, + 2146132608, + 2146167936, + 2146202368, + 2146235776, + 2146268416, + 2146300160, + 2146331136, + 2146361216, + 2146390528, + 2146419200, + 2146446976, + 2146474112, + 2146500480, + 2146526208, + 2146551168, + 2146575488, + 2146599296, + 2146622464, + 2146644864, + 2146666880, + 2146688128, + 2146708992, + 2146729216, + 2146748928, + 2146768128, + 2146786816, + 2146805120, + 2146822784, + 2146840064, + 2146856960, + 2146873344, + 2146889216, + 2146904832, + 2146919936, + 2146934656, + 2146948992, + 2146962944, + 2146976640, + 2146989824, + 2147002752, + 2147015296, + 2147027584, + 2147039488, + 2147051136, + 2147062400, + 2147073408, + 2147084160, + 2147094528, + 2147104768, + 2147114624, + 2147124352, + 2147133696, + 2147142912, + 2147151744, + 2147160448, + 2147168896, + 2147177088, + 2147185152, + 2147192960, + 2147200512, + 2147207936, + 2147215104, + 2147222144, + 2147229056, + 2147235712, + 2147242112, + 2147248384, + 2147254656, + 2147260544, + 2147266432, + 2147272064, + 2147277568, + }, + + + }; \ No newline at end of file diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index b58e183eb..1cde96510 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -326,5 +326,8 @@ extern const Word16 sns_1st_means_32k[2][16]; extern const Word16 ivas_param_upmx_mx_qmap[33]; + +extern const Word32 release_cnst_table[4][201]; // Q31 + /* IVAS_ROM_COM_H */ #endif diff --git a/lib_com/lsf_tools_fx.c b/lib_com/lsf_tools_fx.c index b99fc4753..c2ec76aa5 100644 --- a/lib_com/lsf_tools_fx.c +++ b/lib_com/lsf_tools_fx.c @@ -4286,7 +4286,7 @@ void dctT2_N_apply_matrix_fx( *pt_y = L_add( *pt_y, Mpy_32_32( ( *pt_x++ ), ( *pt_A ) ) ); move32(); pt_A += mat_step_col; /* step +maxtrunc or +1 */ /* ptr indexing*/ - MAC( 1 ); + MAC_C( 1 ); #undef WMC_TOOL_SKIP } pt_y++; @@ -4338,7 +4338,7 @@ void extend_dctN_input_fx( ext_sig[i] = L_add( ext_sig[i], Mpy_32_32( dct_input[j], ptr[i_rev][j] ) ); /* sum up scaled and extended basis vector */ // Q31 + Q - Q31 -> Q move32(); - MAC( 1 ); + MAC_C( 1 ); #undef WMC_TOOL_SKIP } } diff --git a/lib_debug/wmc_auto.h b/lib_debug/wmc_auto.h index 59bbc5bbf..64e2c751a 100644 --- a/lib_debug/wmc_auto.h +++ b/lib_debug/wmc_auto.h @@ -34,7 +34,7 @@ #define ENH_64_BIT_OPERATOR #define ENH_U_32_BIT_OPERATOR #define COMPLEX_OPERATOR -#define CONTROL_CODE_OPS /* enable control code operators such as LT_16, GT_16, ... */ +#define CONTROL_CODE_OPS /* enable control code operators such as LT_16, GT_16, ... */ #define WMOPS_DISABLE_FCN_CALL_PENALIZATION /* do not count the complexity of function calls */ #ifdef WMOPS @@ -123,7 +123,7 @@ void update_mem( void ); ops_cnt += ( _MULT_C * ( x ) ); \ inst_cnt[_MULT] += ( x ); \ } -#define MAC( x ) \ +#define MAC_C( x ) \ { \ ops_cnt += ( _MAC_C * ( x ) ); \ inst_cnt[_MAC] += ( x ); \ @@ -258,7 +258,7 @@ void update_mem( void ); { \ ops_cnt += ( 2 * _TRANS_C * ( x ) ); \ inst_cnt[_TRANS] += ( x ); \ - } + } #else @@ -273,7 +273,7 @@ extern int cntr_push_pop; #define ADD( x ) #define ABS( x ) #define MULT( x ) -#define MAC( x ) +#define MAC_C( x ) #define MOVE( x ) #define STORE( x ) #define LOGIC( x ) @@ -335,29 +335,29 @@ extern int cntr_push_pop; #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 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 LOOP_( x ) OP_COUNT_( _LOOP, ( x ) ) +#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) ) +#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) ) #ifdef WMOPS_DISABLE_FCN_CALL_PENALIZATION -#define FUNC_( x ) ( x ) +#define FUNC_( x ) ( x ) #else -#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) ) +#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) ) #endif -#define MISC_( x ) ABS_( x ) +#define MISC_( x ) ABS_( x ) /* Math Operations */ #define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs ) @@ -401,8 +401,8 @@ extern int cntr_push_pop; #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) +/* 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 ) ) ) @@ -928,7 +928,7 @@ typedef struct unsigned int Madd_32_32_r; /* Complexity Weight of 1 */ unsigned int Msub_32_32; /* Complexity Weight of 1 */ unsigned int Msub_32_32_r; /* Complexity Weight of 1 */ -#endif /* #ifdef ENH_32_BIT_OPERATOR */ +#endif /* #ifdef ENH_32_BIT_OPERATOR */ #ifdef ENH_U_32_BIT_OPERATOR unsigned int UL_addNs; /* Complexity Weight of 1 */ @@ -938,7 +938,7 @@ typedef struct unsigned int Mpy_32_16_uu; /* Complexity Weight of 2 */ unsigned int norm_ul_float; /* Complexity Weight of 1 */ unsigned int UL_deposit_l; /* Complexity Weight of 1 */ -#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ +#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ #ifdef CONTROL_CODE_OPS unsigned int LT_16; /* Complexity Weight of 1 */ @@ -1095,7 +1095,9 @@ void incrIf( const char *func_name ); #ifndef WMOPS #define ELSE else #else /* ifndef WMOPS */ -#define ELSE else if ( incrElse( __func__ ), 0 ); else +#define ELSE \ + else if ( incrElse( __func__ ), 0 ); \ + else void incrElse( const char *func_name ); #endif /* ifndef WMOPS */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 29aacd01a..9c951badf 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -203,7 +203,7 @@ static ivas_error ivas_dec_reconfig_split_rend( { st_ivas->hTdRendHandles[i]->HrFiltSet_p = NULL; move32(); - ivas_td_binaural_close( &st_ivas->hTdRendHandles[i] ); + ivas_td_binaural_close_fx( &st_ivas->hTdRendHandles[i] ); } } } diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h index 331eaadf3..1f2009b66 100644 --- a/lib_isar/isar_prot.h +++ b/lib_isar/isar_prot.h @@ -438,20 +438,6 @@ void lc3plusTimeAlignCldfbPoseCorr( SPLIT_REND_WRAPPER *hSplitBin, Word16 *Q_in ); #endif -void set16_fx( - Word16 y[], /* i/o: Vector to set */ - const Word16 a, /* i : Value to set the vector to */ - const Word16 N /* i : Lenght of the vector */ -); - -void set32_fx( - Word32 y[], /* i/o: Vector to set */ - const Word32 a, /* i : Value to set the vector to */ - const Word16 N /* i : Lenght of the vector */ -); - -Word16 ceil_log_2( - UWord64 val ); void ivas_cmult_fix( Word32 in1_re_fx, Word16 exp_re1, Word32 in1_im_fx, Word16 exp_im1, Word32 in2_re_fx, Word16 exp_re2, Word32 in2_im_fx, Word16 exp_im2, Word32 *out1_re_fx, Word32 *out1_im_fx, Word16 *exp_out1_re, Word16 *exp_out1_im ); diff --git a/lib_isar/isar_splitRenderer_utils.c b/lib_isar/isar_splitRenderer_utils.c index 3e2dd1f41..44b3822a7 100644 --- a/lib_isar/isar_splitRenderer_utils.c +++ b/lib_isar/isar_splitRenderer_utils.c @@ -1561,116 +1561,5 @@ Word32 get_bit( return L_and( state, ( L_shl( 1, (Word16) bit_id ) ) ); } -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 < N; i++ ) - { - y[i] = a; - } - - return; -} - -void set32_fx( - Word32 y[], /* i/o: Vector to set */ - const Word32 a, /* i : Value to set the vector to */ - const Word16 N /* i : Length of the vector */ -) -{ - Word16 i; - - FOR( i = 0; i < N; i++ ) - { - y[i] = a; - move32(); - } - - return; -} -/*-------------------------------------------------------------------* - * ceil_log_2() - * - * calculates ceil(log2(val)) - *-------------------------------------------------------------------*/ - -Word16 ceil_log_2( - UWord64 val ) -{ - - IF( val <= 0 ) - { - assert( 0 ); - } - return val <= 1 ? 0 : val <= 2 ? 1 - : val <= 4 ? 2 - : val <= 8 ? 3 - : val <= 16 ? 4 - : val <= 32 ? 5 - : val <= 64 ? 6 - : val <= 128 ? 7 - : val <= 256 ? 8 - : val <= 512 ? 9 - : val <= 1024 ? 10 - : val <= 2048 ? 11 - : val <= 4096 ? 12 - : val <= 8192 ? 13 - : val <= 16384 ? 14 - : val <= 32768 ? 15 - : val <= 65536 ? 16 - : val <= 131072 ? 17 - : val <= 262144 ? 18 - : val <= 524288 ? 19 - : val <= 1048576 ? 20 - : val <= 2097152 ? 21 - : val <= 4194304 ? 22 - : val <= 8388608 ? 23 - : val <= 16777216 ? 24 - : val <= 33554432 ? 25 - : val <= 67108864 ? 26 - : val <= 134217728 ? 27 - : val <= 268435456 ? 28 - : val <= 536870912 ? 29 - : val <= 1073741824 ? 30 - : val <= 2147483648 ? 31 - : val <= 4294967296 ? 32 - : val <= 8589934592 ? 33 - : val <= 17179869184 ? 34 - : val <= 34359738368 ? 35 - : val <= 68719476736 ? 36 - : val <= 137438953472 ? 37 - : val <= 274877906944 ? 38 - : val <= 549755813888 ? 39 - : val <= 1099511627776 ? 40 - : val <= 2199023255552 ? 41 - : val <= 4398046511104 ? 42 - : val <= 8796093022208 ? 43 - : val <= 17592186044416 ? 44 - : val <= 35184372088832 ? 45 - : val <= 70368744177664 ? 46 - : val <= 140737488355328 ? 47 - : val <= 281474976710656 ? 48 - : val <= 562949953421312 ? 49 - : val <= 1125899906842624 ? 50 - : val <= 2251799813685248 ? 51 - : val <= 4503599627370496 ? 52 - : val <= 9007199254740992 ? 53 - : val <= 18014398509481984 ? 54 - : val <= 36028797018963968 ? 55 - : val <= 72057594037927936 ? 56 - : val <= 144115188075855872 ? 57 - : val <= 288230376151711744 ? 58 - : val <= 576460752303423488 ? 59 - : val <= 1152921504606846976 ? 60 - : val <= 2305843009213693952 ? 61 - : val <= 4611686018427387904 ? 62 - : val <= 9223372036854775807 ? 63 - : 64; -} #endif diff --git a/lib_lc3plus/defines.h b/lib_lc3plus/defines.h index c9909ddf2..f468568a9 100644 --- a/lib_lc3plus/defines.h +++ b/lib_lc3plus/defines.h @@ -731,4 +731,30 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger /* some configurations leave empty translation units. */ extern int fix_empty_translation_unit_warning; +#define FIX_IVAS_LC3PLUS_DUPLICATES +#ifdef FIX_IVAS_LC3PLUS_DUPLICATES +#define Tab_esc_nb Tab_esc_nb_lc3plus +#define POW_ATT_TABLE0 POW_ATT_TABLE0_lc3plus +#define POW_ATT_TABLE1 POW_ATT_TABLE1_lc3plus +#define InvIntTable InvIntTable_lc3plus +#define SineTable320 SineTable320_lc3plus +#define RotVector_320 RotVector_320_lc3plus +#define RotVector_480 RotVector_480_lc3plus +#define SineWindow20 SineWindow20_lc3plus +#define SineWindow40 SineWindow40_lc3plus +#define SineWindow60 SineWindow60_lc3plus +#define SineWindow80 SineWindow80_lc3plus +#define SineWindow120 SineWindow120_lc3plus +#define SineWindow160 SineWindow160_lc3plus +#define SineWindow180 SineWindow180_lc3plus +#define SineWindow320 SineWindow320_lc3plus +#define BASOP_getTables BASOP_getTables_lc3plus +#define ISqrt16 ISqrt16_lc3plus +#define getScaleFactor16 getScaleFactor16_lc3plus +#define Norm32Norm Norm32Norm_lc3plus +#define Scale_sig Scale_sig_lc3plus +#define Copy_Scale_sig Copy_Scale_sig_lc3plus +#define get_size_mpvq_calc_offset_fx get_size_mpvq_calc_offset_fx_lc3plus +#endif + #endif diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index f430f073d..3e5bb8b86 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -445,14 +445,14 @@ void ivas_dirac_dec_close_binaural_data( { IF( hBinaural[pos_idx]->hReverb != NULL ) { - ivas_binaural_reverb_close( &( hBinaural[pos_idx]->hReverb ) ); + ivas_binaural_reverb_close_fx( &( hBinaural[pos_idx]->hReverb ) ); } ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) ); if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL ) { - ivas_dirac_dec_decorr_close( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) ); + ivas_dirac_dec_decorr_close_fx( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) ); } free( hBinaural[pos_idx] ); diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index d99a4ad76..2492bc64a 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -598,823 +598,6 @@ const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = 6.2001e-08f, 2.8483e-08f, 2.6267e-08f }; -const Word32 release_cnst_table[4][201] = // Q31 - { - { - 1913946752, - 1919716352, - 1925351680, - 1930855552, - 1936230784, - 1941479808, - 1946605312, - 1951609728, - 1956495744, - 1961265792, - 1965922304, - 1970467584, - 1974904320, - 1979234560, - 1983460736, - 1987585024, - 1991609856, - 1995537280, - 1999369344, - 2003108480, - 2006756480, - 2010315520, - 2013787520, - 2017174528, - 2020478464, - 2023701248, - 2026844672, - 2029910656, - 2032900992, - 2035817344, - 2038661376, - 2041435008, - 2044139648, - 2046777088, - 2049348864, - 2051856384, - 2054301440, - 2056685312, - 2059009536, - 2061275520, - 2063484672, - 2065638272, - 2067737856, - 2069784448, - 2071779584, - 2073724416, - 2075620096, - 2077467904, - 2079268992, - 2081024512, - 2082735488, - 2084403200, - 2086028416, - 2087612544, - 2089156352, - 2090660864, - 2092127104, - 2093555968, - 2094948480, - 2096305408, - 2097627776, - 2098916352, - 2100172032, - 2101395584, - 2102587776, - 2103749504, - 2104881408, - 2105984384, - 2107059072, - 2108106112, - 2109126400, - 2110120448, - 2111088896, - 2112032512, - 2112951808, - 2113847552, - 2114720128, - 2115570304, - 2116398592, - 2117205504, - 2117991552, - 2118757504, - 2119503616, - 2120230400, - 2120938496, - 2121628288, - 2122300288, - 2122954880, - 2123592576, - 2124213760, - 2124818944, - 2125408384, - 2125982592, - 2126541952, - 2127086848, - 2127617664, - 2128134656, - 2128638336, - 2129128832, - 2129606784, - 2130072192, - 2130525568, - 2130967296, - 2131397376, - 2131816448, - 2132224640, - 2132622080, - 2133009408, - 2133386496, - 2133753856, - 2134111744, - 2134460288, - 2134799744, - 2135130368, - 2135452416, - 2135766144, - 2136071680, - 2136369152, - 2136659072, - 2136941312, - 2137216256, - 2137484160, - 2137744896, - 2137998976, - 2138246400, - 2138487424, - 2138722176, - 2138950656, - 2139173376, - 2139390208, - 2139601408, - 2139807104, - 2140007424, - 2140202624, - 2140392576, - 2140577664, - 2140758016, - 2140933504, - 2141104512, - 2141271040, - 2141433216, - 2141591168, - 2141745024, - 2141894912, - 2142040832, - 2142182912, - 2142321408, - 2142456192, - 2142587392, - 2142715264, - 2142839808, - 2142961152, - 2143079296, - 2143194240, - 2143306240, - 2143415424, - 2143521664, - 2143625216, - 2143725952, - 2143824128, - 2143919744, - 2144012800, - 2144103424, - 2144191744, - 2144277760, - 2144361472, - 2144443136, - 2144522496, - 2144599936, - 2144675200, - 2144748544, - 2144820096, - 2144889600, - 2144957440, - 2145023488, - 2145087744, - 2145150336, - 2145211264, - 2145270656, - 2145328512, - 2145384832, - 2145439616, - 2145493120, - 2145545088, - 2145595776, - 2145645056, - 2145693184, - 2145739904, - 2145785472, - 2145829888, - 2145873152, - 2145915136, - 2145956224, - 2145996032, - 2146034944, - 2146072832, - 2146109696, - 2146145664, - 2146180608, - 2146214656, - 2146247808, - }, - { - 2027355264, - 2030408704, - 2033386624, - 2036290944, - 2039123328, - 2041885440, - 2044578944, - 2047205376, - 2049766528, - 2052263680, - 2054698496, - 2057072384, - 2059387008, - 2061643520, - 2063843328, - 2065987968, - 2068078720, - 2070116864, - 2072103552, - 2074040192, - 2075927936, - 2077767936, - 2079561472, - 2081309568, - 2083013376, - 2084673920, - 2086292352, - 2087869696, - 2089406976, - 2090905216, - 2092365184, - 2093788032, - 2095174528, - 2096525824, - 2097842432, - 2099125632, - 2100375808, - 2101594240, - 2102781312, - 2103938048, - 2105065216, - 2106163456, - 2107233536, - 2108276096, - 2109292032, - 2110281728, - 2111246080, - 2112185728, - 2113101056, - 2113992960, - 2114861824, - 2115708288, - 2116532992, - 2117336448, - 2118119168, - 2118881792, - 2119624704, - 2120348416, - 2121053440, - 2121740288, - 2122409344, - 2123061120, - 2123696128, - 2124314624, - 2124917120, - 2125504128, - 2126075776, - 2126632832, - 2127175296, - 2127703808, - 2128218624, - 2128720000, - 2129208448, - 2129684352, - 2130147712, - 2130599168, - 2131038976, - 2131467264, - 2131884416, - 2132290816, - 2132686592, - 2133072256, - 2133447680, - 2133813504, - 2134169856, - 2134516864, - 2134854784, - 2135184000, - 2135504640, - 2135816960, - 2136121216, - 2136417536, - 2136706048, - 2136987136, - 2137260928, - 2137527552, - 2137787264, - 2138040192, - 2138286592, - 2138526464, - 2138760192, - 2138987776, - 2139209472, - 2139425408, - 2139635712, - 2139840512, - 2140039936, - 2140234240, - 2140423424, - 2140607744, - 2140787200, - 2140962048, - 2141132288, - 2141298048, - 2141459584, - 2141616896, - 2141769984, - 2141919232, - 2142064512, - 2142205952, - 2142343808, - 2142478080, - 2142608768, - 2142736128, - 2142860032, - 2142980864, - 2143098368, - 2143212928, - 2143324544, - 2143433088, - 2143538944, - 2143641984, - 2143742336, - 2143840000, - 2143935232, - 2144027904, - 2144118144, - 2144206080, - 2144291712, - 2144375168, - 2144456320, - 2144535424, - 2144612480, - 2144687488, - 2144760448, - 2144831616, - 2144900992, - 2144968448, - 2145034112, - 2145098112, - 2145160448, - 2145221248, - 2145280256, - 2145337856, - 2145393920, - 2145448576, - 2145501696, - 2145553536, - 2145603968, - 2145653120, - 2145700992, - 2145747456, - 2145792896, - 2145837056, - 2145880064, - 2145922048, - 2145962880, - 2146002560, - 2146041344, - 2146078976, - 2146115712, - 2146151424, - 2146186240, - 2146220160, - 2146253184, - 2146285312, - 2146316672, - 2146347136, - 2146376832, - 2146405760, - 2146433920, - 2146461440, - 2146488192, - 2146514176, - 2146539520, - 2146564224, - 2146588160, - 2146611584, - 2146634368, - 2146656640, - 2146678272, - 2146699264, - 2146719744, - 2146739712, - 2146759168, - 2146778112, - 2146796544, - 2146814464, - 2146832000, - 2146849024, - 2146865664, - }, - { - 2086555136, - 2088125824, - 2089656576, - 2091148416, - 2092602240, - 2094018944, - 2095399680, - 2096745088, - 2098056192, - 2099333888, - 2100578816, - 2101792000, - 2102974080, - 2104125824, - 2105248128, - 2106341760, - 2107407232, - 2108445440, - 2109456896, - 2110442496, - 2111402624, - 2112338176, - 2113249664, - 2114137728, - 2115002880, - 2115845760, - 2116666880, - 2117466880, - 2118246272, - 2119005568, - 2119745280, - 2120465920, - 2121167872, - 2121851776, - 2122517888, - 2123166976, - 2123799168, - 2124414976, - 2125014912, - 2125599360, - 2126168704, - 2126723200, - 2127263360, - 2127789568, - 2128302208, - 2128801408, - 2129287808, - 2129761536, - 2130222976, - 2130672512, - 2131110272, - 2131536768, - 2131952128, - 2132356736, - 2132750848, - 2133134720, - 2133508736, - 2133872896, - 2134227584, - 2134573184, - 2134909696, - 2135237504, - 2135556736, - 2135867648, - 2136170624, - 2136465536, - 2136752896, - 2137032832, - 2137305344, - 2137570816, - 2137829376, - 2138081280, - 2138326528, - 2138565504, - 2138798080, - 2139024768, - 2139245440, - 2139460480, - 2139669888, - 2139873792, - 2140072320, - 2140265856, - 2140454144, - 2140637696, - 2140816384, - 2140990464, - 2141159936, - 2141325056, - 2141485824, - 2141642368, - 2141794944, - 2141943424, - 2142088064, - 2142228992, - 2142366208, - 2142499840, - 2142630016, - 2142756736, - 2142880128, - 2143000448, - 2143117440, - 2143231488, - 2143342592, - 2143450752, - 2143556096, - 2143658624, - 2143758592, - 2143855872, - 2143950592, - 2144043008, - 2144132864, - 2144220416, - 2144305664, - 2144388608, - 2144469504, - 2144548224, - 2144624896, - 2144699648, - 2144772352, - 2144843264, - 2144912256, - 2144979328, - 2145044864, - 2145108480, - 2145170560, - 2145231104, - 2145289856, - 2145347200, - 2145403008, - 2145457408, - 2145510400, - 2145561984, - 2145612160, - 2145661056, - 2145708672, - 2145755136, - 2145800192, - 2145844224, - 2145887104, - 2145928832, - 2145969408, - 2146008960, - 2146047616, - 2146085120, - 2146121600, - 2146157184, - 2146191872, - 2146225664, - 2146258560, - 2146290560, - 2146321792, - 2146352128, - 2146381696, - 2146410496, - 2146438528, - 2146465920, - 2146492416, - 2146518400, - 2146543616, - 2146568192, - 2146592128, - 2146615424, - 2146638080, - 2146660224, - 2146681728, - 2146702720, - 2146723072, - 2146743040, - 2146762368, - 2146781184, - 2146799616, - 2146817408, - 2146834816, - 2146851840, - 2146868352, - 2146884352, - 2146900096, - 2146915328, - 2146930176, - 2146944640, - 2146958720, - 2146972416, - 2146985856, - 2146998784, - 2147011456, - 2147023872, - 2147035904, - 2147047552, - 2147058944, - 2147070080, - 2147080832, - 2147091456, - 2147101696, - 2147111680, - 2147121408, - 2147130880, - 2147140096, - 2147149056, - 2147157760, - 2147166336, - 2147174656, - }, - { - 2106670080, - 2107727232, - 2108757120, - 2109760640, - 2110738432, - 2111691008, - 2112619136, - 2113523328, - 2114404352, - 2115262592, - 2116098816, - 2116913408, - 2117707136, - 2118480256, - 2119233536, - 2119967360, - 2120682240, - 2121378688, - 2122057088, - 2122717952, - 2123361792, - 2123988992, - 2124599936, - 2125195136, - 2125774848, - 2126339584, - 2126889728, - 2127425536, - 2127947520, - 2128456064, - 2128951296, - 2129433856, - 2129903744, - 2130361600, - 2130807424, - 2131241728, - 2131664768, - 2132076928, - 2132478208, - 2132869248, - 2133250048, - 2133620992, - 2133982208, - 2134334080, - 2134676864, - 2135010688, - 2135335936, - 2135652608, - 2135961088, - 2136261504, - 2136554112, - 2136839168, - 2137116800, - 2137387136, - 2137650560, - 2137907072, - 2138156928, - 2138400256, - 2138637184, - 2138867968, - 2139092864, - 2139311744, - 2139524992, - 2139732736, - 2139934976, - 2140131968, - 2140323840, - 2140510720, - 2140692736, - 2140870016, - 2141042688, - 2141210752, - 2141374592, - 2141534080, - 2141689344, - 2141840640, - 2141987968, - 2142131456, - 2142271232, - 2142407424, - 2142539904, - 2142669056, - 2142794752, - 2142917248, - 2143036544, - 2143152640, - 2143265792, - 2143375872, - 2143483264, - 2143587712, - 2143689472, - 2143788544, - 2143885056, - 2143979136, - 2144070656, - 2144159872, - 2144246656, - 2144331264, - 2144413568, - 2144493824, - 2144571904, - 2144647936, - 2144722048, - 2144794240, - 2144864512, - 2144932864, - 2144999552, - 2145064448, - 2145127680, - 2145189248, - 2145249152, - 2145307520, - 2145364480, - 2145419776, - 2145473792, - 2145526272, - 2145577472, - 2145627264, - 2145675776, - 2145723008, - 2145768960, - 2145813760, - 2145857408, - 2145899904, - 2145941376, - 2145981696, - 2146020864, - 2146059136, - 2146096384, - 2146132608, - 2146167936, - 2146202368, - 2146235776, - 2146268416, - 2146300160, - 2146331136, - 2146361216, - 2146390528, - 2146419200, - 2146446976, - 2146474112, - 2146500480, - 2146526208, - 2146551168, - 2146575488, - 2146599296, - 2146622464, - 2146644864, - 2146666880, - 2146688128, - 2146708992, - 2146729216, - 2146748928, - 2146768128, - 2146786816, - 2146805120, - 2146822784, - 2146840064, - 2146856960, - 2146873344, - 2146889216, - 2146904832, - 2146919936, - 2146934656, - 2146948992, - 2146962944, - 2146976640, - 2146989824, - 2147002752, - 2147015296, - 2147027584, - 2147039488, - 2147051136, - 2147062400, - 2147073408, - 2147084160, - 2147094528, - 2147104768, - 2147114624, - 2147124352, - 2147133696, - 2147142912, - 2147151744, - 2147160448, - 2147168896, - 2147177088, - 2147185152, - 2147192960, - 2147200512, - 2147207936, - 2147215104, - 2147222144, - 2147229056, - 2147235712, - 2147242112, - 2147248384, - 2147254656, - 2147260544, - 2147266432, - 2147272064, - 2147277568, - }, - - - }; /*----------------------------------------------------------------------------------* diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h index c80fab8ce..7d7df163c 100644 --- a/lib_rend/ivas_rom_rend.h +++ b/lib_rend/ivas_rom_rend.h @@ -125,8 +125,6 @@ extern const float ivas_reverb_default_fc[]; extern const float ivas_reverb_default_RT60[]; extern const float ivas_reverb_default_DSR[]; -extern const Word32 release_cnst_table[4][201]; // Q31 - /*----------------------------------------------------------------------------------* * Renderer SBA & MC enc/dec matrices *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 448375dfd..9b96ac146 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1628,7 +1628,7 @@ static void clearInputIsm( #ifdef SPLIT_REND_WITH_HEAD_ROT FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) { - ivas_td_binaural_close( &inputIsm->splitTdRendWrappers[i].hBinRendererTd ); + ivas_td_binaural_close_fx( &inputIsm->splitTdRendWrappers[i].hBinRendererTd ); inputIsm->splitTdRendWrappers[i].hHrtfTD = NULL; } #endif @@ -2855,7 +2855,7 @@ static void clearInputMc( { IF( inputMc->splitTdRendWrappers[i].hBinRendererTd != NULL ) { - ivas_td_binaural_close( &inputMc->splitTdRendWrappers[i].hBinRendererTd ); + ivas_td_binaural_close_fx( &inputMc->splitTdRendWrappers[i].hBinRendererTd ); inputMc->splitTdRendWrappers[i].hHrtfTD = NULL; } } @@ -9299,14 +9299,14 @@ void IVAS_REND_cldfbSynthesis_wrapper( const int16_t samplesToProcess, /* i : number of processed samples */ IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filter bank state */ Word16 Q_cldfb, - Word16 Q_out ) + Word16 *Q_out ) { Scale_sig32( h_cldfb->cldfb_state_fx, h_cldfb->p_filter_length, sub( sub( Q_cldfb, 1 ), h_cldfb->Q_cldfb_state ) ); cldfbSynthesis_ivas_fx( realBuffer, imagBuffer, timeOut, samplesToProcess, h_cldfb ); // Q_cldfb - 1 - Q_out = sub( Q_cldfb, 1 ); + *Q_out = sub( Q_cldfb, 1 ); move16(); - h_cldfb->Q_cldfb_state = Q_out; + h_cldfb->Q_cldfb_state = *Q_out; move16(); return; diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 6d7ce0bdf..1ac3c9fea 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -401,7 +401,7 @@ void IVAS_REND_cldfbSynthesis_wrapper( const int16_t samplesToProcess, /* i : number of processed samples */ IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i : filter bank state */ Word16 Q_cldfb, - Word16 Q_out ); + Word16 *Q_out ); #endif -- GitLab From 9e5259ceb1a8ddc45b5294c8d3a40bc3256b77ad Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 13:06:56 +1100 Subject: [PATCH 11/43] clang format fix --- lib_com/ivas_rom_com.c | 7094 ++++++++++++++------------- lib_dec/ivas_binRenderer_internal.c | 26 +- 2 files changed, 3562 insertions(+), 3558 deletions(-) diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 6023812c8..5df975cf8 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -52,3671 +52,3673 @@ const Word32 ivas_brate_tbl[SIZE_IVAS_BRATE_TBL] = IVAS_192k, IVAS_256k, IVAS_384k, IVAS_512k }; - -/*------------------------------------------------------------------------- - * DFT Stereo ROM tables - *------------------------------------------------------------------------*/ - -/*4xERB scale: max of 14 bands*/ -const Word16 dft_band_limits_erb4[STEREO_DFT_ERB4_BANDS] = -{ - 1, 3, 5, 10, 18, 26, 41, 56, 84, 132, 214, 342, 470, 601 -}; - -/*8xERB scale: max of 8 bands*/ -const Word16 dft_band_limits_erb8[STEREO_DFT_ERB8_BANDS] = -{ - 1, 5, 18, 41, 84, 214, 470, 601 -}; - - -const Word16 dft_band_ipd[3][4] = -{ - {0,8,10,13}, - {0,5,6,8}, - {0,2,3,4} -}; - -const Word16 dft_band_res_cod[3][4] = -{ - {0,8,10,11}, - {0,5,6,7}, - {0,5,6,7} -}; - -// Q31 -const Word32 dft_res_gains_q_Q31[][2] = -{ - /* quantization points for joint quantization of prediction gain and residual energy */ - - /* column 1 (|ILD| = 0): */ - {0, 0 }, - {0, 251216928 }, - {0, 487459456 }, - {0, 731632640 }, - {0, 997611392 }, - {0, 1299397248 }, - {0, 1666984192 }, - {0, 2147483647 }, - - /* column 2 (|ILD| = 2): */ - {246151024, 0 }, - {249475328, 247871152 }, - {258660112, 480729248 }, - {274304544, 720918848 }, - {298427200, 981720000 }, - {334663840, 1276185088 }, - {391374592, 1632160640 }, - {485919712, 2091786496 }, - - /* column 3 (|ILD| = 4): */ - {485919712, 0 }, - {492224736, 238188144 }, - {509610752, 461283776 }, - {539117184, 690072384 }, - {584326016, 936189056 }, - {651608832, 1210182144 }, - {755411712, 1534299776 }, - {924504576, 1938292992 }, - - /* column 4 (|ILD| = 6): */ - {713563712, 0 }, - {722237376, 223142880 }, - {746085184, 431184640 }, - {786311872, 642617280 }, - {847364864, 866812416 }, - {936938496, 1111020032 }, - {1072199936, 1390431232 }, - {1285225984, 1720430720 }, - - /* column 5 (|ILD| = 8): */ - {924504576, 0 }, - {934784576, 204139792 }, - {962942400, 393358880 }, - {1010083968, 583482048 }, - {1080789888, 781462848 }, - {1182728704, 991308544 }, - {1332741248, 1221608960 }, - {1559902080, 1475937536 }, - - /* column 6 (|ILD| = 10): */ - {1115604864, 0 }, - {1126709504, 182744416 }, - {1156997632, 351025536 }, - {1207276672, 517958016 }, - {1281710592, 688294272 }, - {1387005952, 863412992 }, - {1537761536, 1046870336 }, - {1757032448, 1234717184 }, - - /* column 7 (|ILD| = 13): */ - {1361843968, 0 }, - {1372924928, 149366080 }, - {1402942464, 285507936 }, - {1452130560, 417893888 }, - {1523515136, 548787328 }, - {1621670144, 677135936 }, - {1756740352, 802203264 }, - {1942499840, 915633344 }, - - /* column 8 (|ILD| = 16): */ - {1559902080, 0 }, - {1569913600, 117815248 }, - {1596862336, 224162928 }, - {1640492800, 325650848 }, - {1702660352, 423060736 }, - {1785997696, 514412544 }, - {1896788608, 597466432 }, - {2042241920, 664027712 }, - - /* column 9 (|ILD| = 19): */ - {1714196608, 0 }, - {1722634112, 90359672 }, - {1745223424, 171238192 }, - {1781415040, 247171072 }, - {1832190080, 318199104 }, - {1898830848, 382271424 }, - {1984989952, 437025792 }, - {2094086528, 475912448 }, - - /* column 10 (|ILD| = 22): */ - {1831427712, 0 }, - {1838194432, 67828272 }, - {1856228992, 128123168 }, - {1884882944, 183977072 }, - {1924581248, 235132272 }, - {1975822336, 279821408 }, - {2040659200, 316058048 }, - {2120554240, 339023232 }, - - /* column 11 (|ILD| = 25): */ - {1918819584, 0 }, - {1924055168, 50102940 }, - {1937964416, 94399088 }, - {1959916032, 135003712 }, - {1990038784, 171579648 }, - {2028424960, 202728896 }, - {2076217216, 226931040 }, - {2133943808, 240762976 }, - - /* column 12 (|ILD| = 30): */ - {2015827840, 0 }, - {2019068416, 29502130 }, - {2027636864, 55420112 }, - {2041056512, 78889960 }, - {2059271424, 99626064 }, - {2082150784, 116769424 }, - {2110128128, 129415952 }, - {2143192960, 135682304 }, - - /* column 13 (|ILD| = 35): */ - {2072441984, 0 }, - {2074364032, 17033840 }, - {2079438464, 31939524 }, - {2087347712, 45337676 }, - {2098012032, 57039312 }, - {2111296384, 66537632 }, - {2127368192, 73321536 }, - {2146126464, 76351632 }, - - /* column 14 (|ILD| = 40): */ - {2104959232, 0 }, - {2106073728, 9723806 }, - {2109011456, 18212808 }, - {2113579136, 25810606 }, - {2119712384, 32401234 }, - {2127314432, 37692632 }, - {2136458496, 41399188 }, - {2147054208, 42945376 }, - - /* column 15 (|ILD| = 45): */ - {2123466240, 0 }, - {2124103936, 5514738 }, - {2125783296, 10322954 }, - {2128390400, 14615774 }, - {2131882240, 18322330 }, - {2136200832, 21283710 }, - {2141376256, 23332410 }, - {2147348352, 24150602 }, - - /* column 16 (|ILD| = 50): */ - {2133943808, 0 }, - {2134306688, 3115998 }, - {2135260160, 5830418 }, - {2136737664, 8250632 }, - {2138715520, 10335839 }, - {2141157120, 11995844 }, - {2144077696, 13136157 }, - {2147440640, 13580687 } -}; - - -/* tables for adaptive Golomb-Rice coding of DFT stereo parameters */ -const Word16 dft_code_itd[] = -{ - 0, 3, 4, 13, 8, 9, 12, 5, 10, 44, 23, 60, 45, 31, 235, 59, 28, 61, 234, 116 -}; - -const Word16 dft_len_itd[] = -{ - 2, 3, 4, 4, 4, 4, 4, 4, 4, 6, 5, 6, 6, 5, 8, 6, 5, 6, 8, 7 -}; - -const Word16 dft_maps_rpg[] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, - 2, 0, 1, 3, 4, 5, 6, 7, - 6, 2, 0, 1, 3, 4, 5, 7, - 7, 5, 2, 0, 1, 3, 4, 6, - 7, 6, 4, 3, 1, 0, 2, 5, - 7, 6, 5, 3, 2, 1, 0, 4, - 7, 6, 5, 4, 3, 2, 0, 1, - 7, 6, 5, 4, 3, 2, 0, 1, - 6, 5, 4, 3, 1, 0, 2, 7, -}; - -const Word16 dft_maps_sg[NO_SYMB_GR_SIDE_G * NO_SYMB_GR_SIDE_G] = -{ - 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, - 1, 0, 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, - 15, 4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 12, 9, 4, 1, 0, 2, 3, 5, 6, 7, 8, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 16, 14, 8, 4, 2, 0, 1, 3, 5, 6, 7, 9, 10, 11, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 18, 16, 14, 10, 5, 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 15, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 21, 19, 17, 15, 8, 4, 2, 0, 1, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 21, 19, 17, 15, 12, 8, 4, 0, 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 21, 19, 17, 15, 13, 11, 9, 3, 0, 1, 2, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 24, 22, 20, 18, 16, 14, 12, 9, 6, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 15, 17, 19, 21, 23, 25, 26, 27, 28, 29, 30, - 25, 23, 21, 19, 17, 15, 13, 11, 9, 6, 0, 1, 2, 3, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27, 28, 29, 30, - 27, 25, 23, 21, 19, 17, 15, 13, 11, 8, 5, 0, 1, 2, 3, 4, 6, 7, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 29, 30, - 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 0, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 28, 29, 30, - 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 30, - 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, - 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 0, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, - 30, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, - 30, 29, 28, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, - 30, 29, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 9, 7, 6, 4, 3, 2, 1, 0, 5, 8, 11, 13, 15, 17, 19, 21, 23, 25, 27, - 30, 29, 28, 27, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 3, 2, 1, 0, 6, 9, 11, 13, 15, 17, 19, 21, 23, 25, - 30, 29, 28, 27, 26, 25, 23, 21, 19, 17, 15, 13, 11, 10, 8, 7, 5, 4, 3, 2, 1, 0, 6, 9, 12, 14, 16, 18, 20, 22, 24, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 18, 16, 14, 12, 10, 8, 7, 6, 5, 4, 2, 1, 0, 3, 9, 11, 13, 15, 17, 19, 21, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 18, 16, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0, 4, 8, 12, 15, 17, 19, 21, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 18, 16, 14, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, 2, 4, 8, 15, 17, 19, 21, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 17, 15, 13, 12, 11, 9, 8, 7, 6, 4, 3, 2, 1, 0, 5, 10, 14, 16, 18, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 15, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, 2, 4, 8, 14, 16, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 11, 10, 8, 7, 6, 5, 3, 2, 0, 1, 4, 9, 12, - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 0, 4, 15, - 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, 0, 1, - 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 -}; - - -/*------------------------------------------------------------------------- - * Range Coder ROM tables - *------------------------------------------------------------------------*/ - -/* Create separate tables for cumulative frequency and symbol frequency */ -const UWord16 cum_freq_ari_pk_s17_LC_ext[RANGE_N_CONTEXT][1 + RANGE_N_SYMBOLS] = -{ - { 0,16,47,153,241,269,325,468,591,674,798,912,1017,1082,1183,1277,1364,16384 }, - { 0,7401,7844,7886,7899,12065,12718,12790,12805,14099,14476,14533,14549,15058,15264,15299,15310,16384 }, - { 0,4362,6345,6864,7038,9037,11049,11736,12002,12569,13301,13656,13822,14021,14334,14515,14607,16384 }, - { 0,2955,5183,5822,6013,8153,10671,11614,11943,12586,13540,14025,14232,14437,14770,14978,15080,16384 }, - { 0,3155,4981,5615,5855,7969,9953,10739,11073,11936,12837,13208,13383,13767,14203,14400,14498,16384 }, - { 0,1216,2630,3264,3558,4831,6679,7661,8157,8709,9622,10204,10542,10799,11243,11568,11777,16384 }, - { 0,1759,3641,4350,4612,6325,8678,9732,10161,10790,11790,12361,12642,12883,13295,13566,13720,16384 }, - { 0,1109,2705,3433,3732,5226,7532,8732,9263,9978,11142,11842,12188,12490,12986,13321,13520,16384 }, - { 0,11524,13046,13170,13191,14956,15708,15813,15837,16028,16162,16195,16204,16245,16282,16295,16300,16384 }, - { 0,8027,10586,10909,10974,13291,14861,15157,15232,15535,15824,15914,15943,16014,16090,16123,16136,16384 }, - { 0,834,2034,2674,2997,4087,5843,6891,7455,8030,9013,9688,10085,10376,10893,11277,11528,16384 }, - { 0,6038,9086,9451,9519,12332,14521,14913,15003,15329,15711,15848,15893,15955,16045,16091,16111,16384 }, - { 0,4732,7685,8354,8545,10717,12924,13618,13852,14291,14842,15083,15181,15314,15491,15582,15625,16384 }, - { 0,745,1783,2347,2655,3537,4963,5864,6406,6863,7664,8248,8634,8891,9351,9708,9958,16384 }, - { 0,3957,6794,7669,7998,9743,11676,12498,12869,13313,13894,14186,14332,14498,14714,14835,14906,16384 }, - { 0,2779,5388,6021,6201,8582,11352,12260,12544,13117,13981,14408,14580,14751,15039,15213,15298,16384 }, - { 0,448,1160,1625,1920,2576,3706,4518,5053,5474,6234,6835,7262,7531,8032,8446,8758,16384 }, - { 0,1,2,1555,2246,2247,2248,3489,4112,5449,6596,7302,7710,8311,8876,9266,9517,16384 }, - { 0,2496,4910,5544,5722,8049,10799,11689,11973,12583,13467,13878,14047,14234,14537,14712,14803,16384 }, - { 0,921,2222,2880,3188,4407,6321,7406,7955,8573,9616,10296,10679,10978,11502,11880,12118,16384 }, - { 0,2620,4443,5017,5233,7072,9213,10083,10441,11049,11954,12442,12676,12918,13310,13565,13705,16384 }, - { 0,11205,13084,13178,13187,15164,16010,16081,16091,16213,16303,16321,16325,16340,16355,16360,16362,16384 }, - { 0,358,916,1288,1542,2055,2937,3594,4062,4399,5017,5524,5907,6136,6573,6941,7236,16384 }, - { 0,3575,5093,5536,5735,7408,9185,9878,10188,10727,11497,11933,12165,12410,12794,13019,13166,16384 }, - { 0,1,2,640,1036,1037,1038,1670,2096,2696,3287,3732,4056,4417,4800,5106,5339,16384 }, - { 0,969,1397,1518,1578,2633,3338,3566,3675,4197,4664,4857,4957,5288,5625,5783,5874,16384 }, - { 0,10458,12104,12294,12331,14246,15264,15437,15481,15752,15971,16031,16050,16120,16186,16210,16218,16384 }, - { 0,7178,9744,10039,10093,12701,14612,14961,15042,15360,15732,15869,15917,15978,16070,16117,16139,16384 }, - { 0,1298,2418,2879,3113,4146,5509,6227,6621,7053,7755,8229,8539,8776,9186,9492,9714,16384 }, - { 0,4957,7785,8252,8357,10978,13372,13955,14114,14561,15140,15378,15464,15570,15730,15820,15860,16384 }, - { 0,4823,8164,8570,8647,11604,14169,14653,14763,15105,15554,15727,15785,15852,15960,16018,16045,16384 }, - { 0,4735,7010,7517,7660,9986,12230,12914,13131,13666,14374,14689,14814,14972,15212,15342,15404,16384 }, - { 0,3363,5881,6658,6941,8864,11113,12015,12368,12889,13643,14019,14203,14394,14665,14823,14906,16384 }, - { 0,2569,4996,5779,6068,7917,10251,11209,11602,12129,12918,13321,13520,13696,13976,14155,14259,16384 }, - { 0,209,577,848,1046,1378,1982,2465,2835,3072,3513,3893,4202,4374,4703,4994,5241,16384 }, - { 0,2074,4337,5048,5274,7319,10003,11066,11446,12105,13112,13652,13885,14100,14464,14691,14810,16384 }, - { 0,1619,3560,4288,4550,6381,8955,10102,10543,11239,12362,12982,13261,13516,13958,14234,14381,16384 }, - { 0,89,257,441,582,734,1024,1325,1568,1716,1983,2222,2430,2545,2750,2941,3109,16384 }, - { 0,2202,3563,4044,4264,5686,7344,8100,8476,9006,9835,10331,10612,10864,11304,11599,11787,16384 }, - { 0,1220,2801,3492,3784,5223,7387,8496,8998,9640,10711,11369,11711,11993,12486,12829,13035,16384 }, - { 0,12626,13813,13903,13917,15396,15906,15972,15987,16139,16230,16251,16257,16289,16315,16323,16326,16384 }, - { 0,1579,3191,3831,4099,5678,7788,8761,9206,9842,10821,11388,11681,11958,12417,12722,12902,16384 }, - { 0,597,1514,2064,2379,3237,4679,5637,6213,6733,7649,8316,8755,9052,9599,10023,10323,16384 }, - { 0,9273,11762,12080,12151,14038,15210,15446,15514,15725,15929,15995,16019,16068,16124,16148,16158,16384 }, - { 0,9238,11681,11852,11872,14306,15644,15801,15828,16013,16183,16231,16243,16266,16297,16312,16318,16384 }, - { 0,6791,9200,9531,9594,12240,14178,14552,14639,15064,15506,15643,15687,15785,15908,15960,15983,16384 }, - { 0,7175,10415,10905,11033,13038,14621,15002,15123,15367,15651,15762,15806,15864,15938,15974,15992,16384 }, - { 0,5060,7703,8132,8225,10934,13270,13778,13911,14397,14972,15173,15242,15367,15537,15619,15654,16384 }, - { 0,3721,6311,6857,6992,9557,12180,12895,13098,13671,14418,14718,14830,14984,15212,15333,15390,16384 }, - { 0,5971,9288,10044,10269,11991,13680,14228,14437,14750,15130,15293,15374,15459,15579,15642,15677,16384 }, - { 0,3047,5311,5907,6078,8339,10850,11679,11946,12580,13442,13854,14024,14220,14534,14716,14810,16384 }, - { 0,2061,4280,4993,5228,7201,9735,10735,11097,11708,12606,13082,13295,13498,13836,14043,14161,16384 }, - { 0,4738,7949,8880,9234,10781,12502,13214,13531,13897,14355,14593,14718,14835,14998,15096,15153,16384 }, - { 0,3237,5045,5632,5860,7609,9702,10608,10986,11571,12476,12978,13230,13451,13830,14074,14208,16384 }, - { 0,1833,3889,4677,5028,6422,8379,9378,9884,10350,11086,11545,11809,12003,12327,12559,12711,16384 }, - { 0,3989,6858,7352,7459,10254,12936,13571,13735,14240,14895,15153,15242,15364,15548,15646,15690,16384 }, - { 0,1463,3197,3909,4220,5626,7609,8632,9127,9657,10520,11078,11380,11607,11991,12265,12442,16384 }, - { 0,14233,15083,15108,15110,16069,16300,16314,16316,16352,16370,16373,16374,16377,16380,16381,16382,16384 }, - { 0,1,2,2610,3293,3294,3295,5097,5671,8467,10332,11119,11437,12223,12850,13185,13345,16384 }, - { 0,2010,4053,4696,4910,6879,9391,10386,10750,11393,12376,12886,13119,13348,13726,13967,14099,16384 }, - { 0,7586,10517,10758,10791,13543,15346,15577,15619,15846,16082,16150,16169,16202,16245,16265,16273,16384 }, - { 0,3059,5772,6369,6524,9041,11801,12582,12813,13361,14115,14439,14567,14714,14944,15075,15141,16384 }, - { 0,8643,10594,10813,10856,13274,14686,14920,14975,15350,15680,15771,15799,15897,16003,16042,16057,16384 }, - { 0,6720,8878,9325,9467,11564,13248,13744,13929,14384,14880,15087,15167,15311,15488,15569,15607,16384 }, -}; - -const UWord16 sym_freq_ari_pk_s17_LC_ext[RANGE_N_CONTEXT][RANGE_N_SYMBOLS] = -{ - { 16,31,106,88,28,56,143,123,83,124,114,105,65,101,94,87,15020 }, - { 7401,443,42,13,4166,653,72,15,1294,377,57,16,509,206,35,11,1074 }, - { 4362,1983,519,174,1999,2012,687,266,567,732,355,166,199,313,181,92,1777 }, - { 2955,2228,639,191,2140,2518,943,329,643,954,485,207,205,333,208,102,1304 }, - { 3155,1826,634,240,2114,1984,786,334,863,901,371,175,384,436,197,98,1886 }, - { 1216,1414,634,294,1273,1848,982,496,552,913,582,338,257,444,325,209,4607 }, - { 1759,1882,709,262,1713,2353,1054,429,629,1000,571,281,241,412,271,154,2664 }, - { 1109,1596,728,299,1494,2306,1200,531,715,1164,700,346,302,496,335,199,2864 }, - { 11524,1522,124,21,1765,752,105,24,191,134,33,9,41,37,13,5,84 }, - { 8027,2559,323,65,2317,1570,296,75,303,289,90,29,71,76,33,13,248 }, - { 834,1200,640,323,1090,1756,1048,564,575,983,675,397,291,517,384,251,4856 }, - { 6038,3048,365,68,2813,2189,392,90,326,382,137,45,62,90,46,20,273 }, - { 4732,2953,669,191,2172,2207,694,234,439,551,241,98,133,177,91,43,759 }, - { 745,1038,564,308,882,1426,901,542,457,801,584,386,257,460,357,250,6426 }, - { 3957,2837,875,329,1745,1933,822,371,444,581,292,146,166,216,121,71,1478 }, - { 2779,2609,633,180,2381,2770,908,284,573,864,427,172,171,288,174,85,1086 }, - { 448,712,465,295,656,1130,812,535,421,760,601,427,269,501,414,312,7626 }, - { 1,1,1553,691,1,1,1241,623,1337,1147,706,408,601,565,390,251,6867 }, - { 2496,2414,634,178,2327,2750,890,284,610,884,411,169,187,303,175,91,1581 }, - { 921,1301,658,308,1219,1914,1085,549,618,1043,680,383,299,524,378,238,4266 }, - { 2620,1823,574,216,1839,2141,870,358,608,905,488,234,242,392,255,140,2679 }, - { 11205,1879,94,9,1977,846,71,10,122,90,18,4,15,15,5,2,22 }, - { 358,558,372,254,513,882,657,468,337,618,507,383,229,437,368,295,9148 }, - { 3575,1518,443,199,1673,1777,693,310,539,770,436,232,245,384,225,147,3218 }, - { 1,1,638,396,1,1,632,426,600,591,445,324,361,383,306,233,11045 }, - { 969,428,121,60,1055,705,228,109,522,467,193,100,331,337,158,91,10510 }, - { 10458,1646,190,37,1915,1018,173,44,271,219,60,19,70,66,24,8,166 }, - { 7178,2566,295,54,2608,1911,349,81,318,372,137,48,61,92,47,22,245 }, - { 1298,1120,461,234,1033,1363,718,394,432,702,474,310,237,410,306,222,6670 }, - { 4957,2828,467,105,2621,2394,583,159,447,579,238,86,106,160,90,40,524 }, - { 4823,3341,406,77,2957,2565,484,110,342,449,173,58,67,108,58,27,339 }, - { 4735,2275,507,143,2326,2244,684,217,535,708,315,125,158,240,130,62,980 }, - { 3363,2518,777,283,1923,2249,902,353,521,754,376,184,191,271,158,83,1478 }, - { 2569,2427,783,289,1849,2334,958,393,527,789,403,199,176,280,179,104,2125 }, - { 209,368,271,198,332,604,483,370,237,441,380,309,172,329,291,247,11143 }, - { 2074,2263,711,226,2045,2684,1063,380,659,1007,540,233,215,364,227,119,1574 }, - { 1619,1941,728,262,1831,2574,1147,441,696,1123,620,279,255,442,276,147,2003 }, - { 89,168,184,141,152,290,301,243,148,267,239,208,115,205,191,168,13275 }, - { 2202,1361,481,220,1422,1658,756,376,530,829,496,281,252,440,295,188,4597 }, - { 1220,1581,691,292,1439,2164,1109,502,642,1071,658,342,282,493,343,206,3349 }, - { 12626,1187,90,14,1479,510,66,15,152,91,21,6,32,26,8,3,58 }, - { 1579,1612,640,268,1579,2110,973,445,636,979,567,293,277,459,305,180,3482 }, - { 597,917,550,315,858,1442,958,576,520,916,667,439,297,547,424,300,6061 }, - { 9273,2489,318,71,1887,1172,236,68,211,204,66,24,49,56,24,10,226 }, - { 9238,2443,171,20,2434,1338,157,27,185,170,48,12,23,31,15,6,66 }, - { 6791,2409,331,63,2646,1938,374,87,425,442,137,44,98,123,52,23,401 }, - { 7175,3240,490,128,2005,1583,381,121,244,284,111,44,58,74,36,18,392 }, - { 5060,2643,429,93,2709,2336,508,133,486,575,201,69,125,170,82,35,730 }, - { 3721,2590,546,135,2565,2623,715,203,573,747,300,112,154,228,121,57,994 }, - { 5971,3317,756,225,1722,1689,548,209,313,380,163,81,85,120,63,35,707 }, - { 3047,2264,596,171,2261,2511,829,267,634,862,412,170,196,314,182,94,1574 }, - { 2061,2219,713,235,1973,2534,1000,362,611,898,476,213,203,338,207,118,2223 }, - { 4738,3211,931,354,1547,1721,712,317,366,458,238,125,117,163,98,57,1231 }, - { 3237,1808,587,228,1749,2093,906,378,585,905,502,252,221,379,244,134,2176 }, - { 1833,2056,788,351,1394,1957,999,506,466,736,459,264,194,324,232,152,3673 }, - { 3989,2869,494,107,2795,2682,635,164,505,655,258,89,122,184,98,44,694 }, - { 1463,1734,712,311,1406,1983,1023,495,530,863,558,302,227,384,274,177,3942 }, - { 14233,850,25,2,959,231,14,2,36,18,3,1,3,3,1,1,2 }, - { 1,1,2608,683,1,1,1802,574,2796,1865,787,318,786,627,335,160,3039 }, - { 2010,2043,643,214,1969,2512,995,364,643,983,510,233,229,378,241,132,2285 }, - { 7586,2931,241,33,2752,1803,231,42,227,236,68,19,33,43,20,8,111 }, - { 3059,2713,597,155,2517,2760,781,231,548,754,324,128,147,230,131,66,1243 }, - { 8643,1951,219,43,2418,1412,234,55,375,330,91,28,98,106,39,15,327 }, - { 6720,2158,447,142,2097,1684,496,185,455,496,207,80,144,177,81,38,777 }, -}; - - -/*------------------------------------------------------------------------- - * ECLVQ Stereo ROM tables - *------------------------------------------------------------------------*/ - -/* table with round(ECSQ_PROB_TOTAL / index) for entropy coding, with i in {1, .., ECSQ_SEGMENT_SIZE} */ -const UWord16 ECSQ_tab_inverse[1 + ECSQ_SEGMENT_SIZE] = -{ - 0, 16384, 8192, 5461, 4096, 3277, 2731, 2341, 2048 -}; - - -const Word16 tdm_bit_allc_tbl[5][6] = -{ - /* IC -- UC -- GC -- TM --AC */ - { 1650, 3500, 0, 4400, 0, 5000 }, /* IVAS_13k2 */ - { 1650, 3500, 0, 5000, 0, 5000 }, /* IVAS_16k4 */ - { 1650, 3500, 0, 6000, 0, 5000 }, /* IVAS_24k4 */ - { 1650, 6050, 0, 10000, 0, 10000 }, /* IVAS_32k */ - { 1650, 6050, 0, 13000, 0, 14000 } /* IVAS_48k */ -}; - - -const Word16 fast_FCB_bits_2sfr[] = {8, 14, 18, 20, 24, 128/*stop value*/}; - -const Word16 fast_FCB_rates_2sfr[] = {/*16*50,*/ (8+14)*50, 28*50, 32*50, 34*50, 36*50, 38*50, 40*50, 42*50, 44*50, 48*50}; - - -/*----------------------------------------------------------------------------------* - * MDCT Stereo ROM tables - *----------------------------------------------------------------------------------*/ - - /* PsychLPC */ - -const SpectrumWarping sw32000Hz[] = -{{ - { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, - 6, 8, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, - 14, 16, 18, 18, 18, 20, 22, 22, 22, 24, 26, 26, 26, 28, 30, 32 - }, - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, - 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10 - }, -}}; - -const SpectrumWarping sw25600Hz[] = -{{ - { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, - 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 10, 12, 12, 12, 12, - 12, 12, 14, 14, 14, 14, 14, 16, 16, 18, 18, 18, 18, 18, 20, 20 - }, - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 - }, -}}; - -const SpectrumWarping sw16000Hz[] = -{{ - { - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 - }, - { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 - }, -}}; - -const MDCTStereoBands_config mdctStereoBands_32000_640[] = -{{ - /*TCX 20*/ - { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, - 12, 20, 20, 20, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 42, - 64, 64, 96, 160}, - {44, 41,38, 29},/*number of bands for frame lengths 960, 640, 512, 320 respectively*/ - - /*TCX 10*/ - { - 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 20, 32, 32, - 32, 48, 80 - }, - {33, 29, 26, 18}/*number of bands for frame lengths 480, 320, 256, 160 respectively*/ -}}; - - -const Word16 dft_cng_coh_u2i[9] = { 4, 5, 3, 6, 2, 7, 1, 8, 0 }; /* Coherence unary codeword -> residual codeword conversion table */ - -const Word16 dft_cng_coh_i2u[9] = { 8, 6, 4, 2, 0, 1, 3, 5, 7 }; /* Coherence residual codeword -> unary codeword conversion table */ - -const Word16 dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1] = { 15, 16, 17, 18 }; - - -const Word16 DirAC_band_grouping_12[12 + 1] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 11, 17, 25, 40, 60 -}; - - -const Word16 DirAC_band_grouping_6[6 + 1] = -{ - 0, 1, 4, 8, 20, 30, 60 -}; - -const Word16 DirAC_band_grouping_5[5 + 1] = -{ - 0, 1, 3, 7, 15, 60 -}; - -const Word16 DirAC_block_grouping[MAX_PARAM_SPATIAL_SUBFRAMES + 1] = -{ - 0, 4, 8, 12, 16 -}; - -const Word16 DirAC_block_grouping_5ms_MDFT[MAX_PARAM_SPATIAL_SUBFRAMES + 1] = -{ - 0, 1, 2, 3, 4 -}; - -const Word32 c_weights_fx[DIRAC_NO_FB_BANDS_MAX] /* Q30 */ = { 106970960, 1033798336, 1065867776, 1071704704, 1073381888, 1073741824, 1073494016, 1072883072, 1072012032, 1070930560, 1069665600, 1068232640, 1066641792, 1064899968, 1063012224, 1060982464, 1058814144, 1056510016, 1054072832, 1051505280, 1048809664, 1045988480, 1043044160, 1039979072, 1036795776, 1033496576, 1030084096, 1026560960, 1022929600, 1019192512, 1015352576, 1011412416, 1007374720, 1003242112, 999017472, 994703488, 990302976, 985818688, 981253568, 976610304, 971891712, 967100672, 962240064, 957312576, 952321088, 947268224, 942156992, 936990080, 931770048, 926499840, 921182016, 915819200, 910414208, 904969344, 899487488, 893970944, 888422272, 882843840, 877238144, 871607552, 865954432, 860280896, 854589184, 848881728, 843160384, 837427328, 831684672, 825934208, 820178240, 814418240, 808656320, 802894208, 797133568, 791376192, 785623744, 779877568, 774139520, 768410880, 762693184, 756987904, 751296064, 745619328, 739958784, 734315584, 728691008, 723086208, 717502016, 711939712, 706400064, 700884096, 695392768, 689926912, 684487232, 679074688, 673689856, 668333504, 663006464, 657709056, 652442176, 647206144, 642001600, 636828992, 631688896, 626581696, 621507776, 616467520, 611461184, 606489344, 601552064, 596649792, 591782528, 586950784, 582154560, 577394112, 572669696, 567981312, 563329088, 558713152, 554133568, 549590464, 545083840, 540613760, 536180160, 531783104, 527422528, 523098464, 518810784, 514559520, 510344672, 506165856, 502023360, 497916832, 493846304, 489811488, 485812448, 481848832, 477920672, 474027808, 470169952, 466347008, 462558848, 458805152, 455085920, 451400736, 447749600, 444132160, 440548320, 436997792, 433480416, 429995904, 426544032, 423124608, 419737376, 416382144, 413058720, 409766720, 406505984, 403276288, 400077280, 396908768, 393770656, 390662496, 387584064, 384535200, 381515616, 378525024, 375563200, 372629952, 369724864, 366847872, 363998592, 361176672, 358382176, 355614592, 352873760, 350159456, 347471328, 344809216, 342172864, 339562048, 336976384, 334415808, 331879840, 329368576, 326881472, 324418432, 321979104, 319563392, 317170976, 314801664, 312455232, 310131328, 307829856, 305550528, 303293088, 301057440, 298843168, 296650176, 294478304, 292327168, 290196672, 288086432, 285996512, 283926432, 281876224, 279845472, 277834016, 275841792, 273868480, 271913856, 269977792, 268059968, 266160304, 264278672, 262414768, 260568368, 258739360, 256927520, 255132768, 253354752, 251593392, 249848448, 248119936, 246407424, 244710816, 243030080, 241364928, 239715120, 238080672, 236461248, 234856752, 233267088, 231692016, 230131440, 228585136, 227053024, 225534848, 224030544, 222539872, 221062832 }; - -/*----------------------------------------------------------------------* -* SPAR ROM tables -*-----------------------------------------------------------------------*/ - -const ivas_spar_br_table_t ivas_spar_br_table_consts[IVAS_SPAR_BR_TABLE_LEN] = -{ -/* When AGC is ON additional (AGC_BITS_PER_CH+1) bits may be taken from each core-coder channel - so minimum core-coder bitrate per channel can be min core-coder bitrates as per the table - AGC_BITS_PER_CH */ - { 13200, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 10000, 8150, 13150 } }, - { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, - - { 16400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 13200, 11350, 16350 } }, - { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, - - { 24400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 16400, 14850, 24350 } }, - { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, - - { 32000, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 24000, 20450, 31950 } }, - { { 21, 1, 5, 1 },{ 15, 1, 5, 1 },{ 15, 1, 3, 1 } }, 0, 0, 0 }, - - { 48000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 24000, 21000, 31950 },{ 16000, 15000, 20400 } }, - { { 15, 7, 5, 1 },{ 15, 7, 3, 1 },{ 7, 7, 3, 1 } }, 1, 0, 0 }, - - { 64000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 38000, 34050, 56000 },{ 16000, 15600, 20400 } },{ { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 1, 0 }, - - { 80000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 46000, 43000, 56000 },{ 24000, 23000, 31950 } }, - { { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 0, 0 }, - - { 96000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 47000, 42600, 56000 },{ 23000, 22600, 31950 },{ 16000, 15600, 20400 } }, - { { 21, 9, 9, 1 },{ 21, 7, 5, 1 },{ 21, 7, 5, 1 } }, 1, 0, 0 }, - - { 128000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 55000, 50000, 56000 },{ 36000, 36000, 56000 },{ 27000, 27000, 31950 } }, - { { 21, 11, 9, 1 },{ 21, 9, 7, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, - - { 160000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 74000, 70900, 112000 },{ 41000, 40050, 56000 },{ 35000, 34050, 56000 } }, - { { 21, 11, 11, 1 },{ 21, 9, 9, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, - - { 192000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 90000, 87900, 112000 },{ 50000, 48050, 56000 },{ 42000, 41050, 56000 } }, - { { 21, 11, 11, 1 },{ 21, 9, 9, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, - - { 256000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 90000, 85000, 112000 },{ 70000, 69000, 112000 },{ 50000, 48950, 56000 },{ 36400, 35600, 56000 } }, - { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 256000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 84650, 83000, 112000 },{ 65850, 64550, 56000 },{ 47000, 46100, 48000 },{ 28200, 27650, 40000 } }, - { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 256000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 76300, 73550, 112000 },{ 59350, 57200, 56000 },{ 42400, 40850, 48000 },{ 25450, 24500, 40000 } }, - { { 31, 11, 11, 1 },{ 1, 1, 1, 1 }, { 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 384000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 100000, 100000, 128000 },{ 79850, 79850, 104000 },{ 66600, 66600, 104000 } }, - { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 384000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 105350, 103300, 112000 },{ 75200, 73750, 96000 },{ 45100, 44250, 48000 } }, - { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 384000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 124300, 121550, 128000 },{ 96700, 94550, 112000 },{ 69050, 67500, 96000 },{ 41450, 40500, 48000 } }, - { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 512000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 }, {118450, 118450, 128000 } }, - { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 512000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 124000, 124000, 128000 },{ 124000, 124000, 128000 },{ 125200, 118450, 128000 },{ 76300, 73000, 128000 } }, - { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, - - { 512000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 118000, 118000, 128000 },{ 118000, 118000, 128000 },{ 117200, 109250, 128000 },{ 72300, 69000, 128000 } }, - { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, -}; - -const ivas_spar_br_table_t ivas_spar_br_table_consts_fx[IVAS_SPAR_BR_TABLE_LEN] = /*ceilf(log2f)*/ -{ - /* When AGC is ON additional (AGC_BITS_PER_CH+1) bits may be taken from each core-coder channel - so minimum core-coder bitrate per channel can be min core-coder bitrates as per the table - AGC_BITS_PER_CH */ - { 13200, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 10000, 8150, 13150 } }, - { { 4, 0, 3, 0 },{ 4, 0, 2, 0 },{ 3, 0, 2, 0 } }, 0, 0, 0 }, - - { 16400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 13200, 11350, 16350 } }, - { { 4, 0, 3, 0 },{ 4, 0, 2, 0 },{ 3, 0, 2, 0 } }, 0, 0, 0 }, - - { 24400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 16400, 14850, 24350 } }, - { { 4, 0, 3, 0 },{ 4, 0, 2, 0 },{ 3, 0, 2, 0 } }, 0, 0, 0 }, - - { 32000, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 24000, 20450, 31950 } }, - { { 5, 0, 3, 0 },{ 4, 0, 3, 0 },{ 4, 0, 2, 0 } }, 0, 0, 0 }, - - { 48000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 24000, 21000, 31950 },{ 16000, 15000, 20400 } }, - { { 4, 3, 3, 0 },{ 4, 3, 2, 0 },{ 3, 3, 2, 0 } }, 1, 0, 0 }, - - { 64000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 38000, 34050, 56000 },{ 16000, 15600, 20400 } },{ { 5, 3, 3, 0 },{ 4, 3, 3, 0 },{ 4, 3, 2, 0 } }, 1, 1, 0 }, - - { 80000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 46000, 43000, 56000 },{ 24000, 23000, 31950 } }, - { { 5, 3, 3, 0 },{ 4, 3, 3, 0 },{ 4, 3, 2, 0 } }, 1, 0, 0 }, - - { 96000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 47000, 42600, 56000 },{ 23000, 22600, 31950 },{ 16000, 15600, 20400 } }, - { { 5, 4, 4, 0 },{ 5, 3, 3, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, - - { 128000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 55000, 50000, 56000 },{ 36000, 36000, 56000 },{ 27000, 27000, 31950 } }, - { { 5, 4, 4, 0 },{ 5, 4, 3, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, - - { 160000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 74000, 70900, 112000 },{ 41000, 40050, 56000 },{ 35000, 34050, 56000 } }, - { { 5, 4, 4, 0 },{ 5, 4, 4, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, - - { 192000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 90000, 87900, 112000 },{ 50000, 48050, 56000 },{ 42000, 41050, 56000 } }, - { { 5, 4, 4, 0 },{ 5, 4, 4, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, - - { 256000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 90000, 85000, 112000 },{ 70000, 69000, 112000 },{ 50000, 48950, 56000 },{ 36400, 35600, 56000 } }, - { { 5, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 256000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 84650, 83000, 112000 },{ 65850, 64550, 56000 },{ 47000, 46100, 48000 },{ 28200, 27650, 40000 } }, - { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 256000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 76300, 73550, 112000 },{ 59350, 57200, 56000 },{ 42400, 40850, 48000 },{ 25450, 24500, 40000 } }, - { { 5, 4, 4, 0 },{ 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 384000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 100000, 100000, 128000 },{ 79850, 79850, 104000 },{ 66600, 66600, 104000 } }, - { { 5, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 384000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 105350, 103300, 112000 },{ 75200, 73750, 96000 },{ 45100, 44250, 48000 } }, - { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 384000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 124300, 121550, 128000 },{ 96700, 94550, 112000 },{ 69050, 67500, 96000 },{ 41450, 40500, 48000 } }, - { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 512000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 }, {118450, 118450, 128000 } }, - { { 5, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 512000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 124000, 124000, 128000 },{ 124000, 124000, 128000 },{ 125200, 118450, 128000 },{ 76300, 73000, 128000 } }, - { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, - - { 512000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 118000, 118000, 128000 },{ 118000, 118000, 128000 },{ 117200, 109250, 128000 },{ 72300, 69000, 128000 } }, - { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, -}; -const ivas_freq_models_t ivas_arith_pred_r_consts[TOTAL_PRED_QUANT_STRATS_ARITH] = -{ - /* entry for 1 quantization points */ - { - /* pred_R real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* pred_R real : values for general and differential */ - { 0 },{ 0 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 7 quantization points for br_table_idx >= 2 */ - { - /* pred_R real */ - { - { 0,546,1092,2184,8740,2184,1092,546, }, - { 0,1779,2116,2516,3562,2516,2116,1779, }, - { 0,1848,2614,5229,2614,1848,1307,924, }, - { 0,924,1307,1848,2614,5229,2614,1848, }, - }, - /* pred_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* pred_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 15 quantization points for br_table_idx >= 2 */ - { - /* pred_R real */ - { - { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, - { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, - { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, - { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, - }, - /* pred_R real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, - }, - /* pred_R real : values for general and differential */ - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 21 quantization points for br_table_idx >= 2 */ - { - /* pred_R real */ - { - { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, - { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, - { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, - { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 31 quantization points */ - { - /* pred real */ - { - { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, - { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, - { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, - { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, } - }, - /* pred real differential */ - { - { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, - { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, - { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, - { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, } - }, - /* pred real : values for general and differential */ - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, - /* pred real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 7 quantization points for br_table_idx < 2 */ - { - /* pred_R real */ - { - { 0,327,778,1851,10472,1851,778,327, }, - { 0,1057,1630,2514,5982,2514,1630,1057, }, - { 0,1668,2572,6122,2572,1668,1081,701, }, - { 0,701,1081,1668,2572,6122,2572,1668, }, - }, - /* pred_R real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* pred_R real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 15 quantization points for br_table_idx < 2 */ - { - /* pred real */ - { - { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, - { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, - { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, - { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, } - }, - /* pred real differential */ - { - { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, - { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, - { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, - { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, } - }, - /* pred real : values for general and differential */ - {-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7}, - { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, - /* pred real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 21 quantization points for br_table_idx < 2 */ - { - /* pred_R real */ - { - { 0,1,1,4,9,23,56,133,318,756,1799,10184,1799,756,318,133,56,23,9,4,1,1, }, - { 0,41,64,98,152,234,362,558,861,1329,2049,4888,2049,1329,861,558,362,234,152,98,64,41, }, - { 0,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64,41,26, }, - { 0,26,41,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64, }, - }, - /* pred_R real differential */ - { - { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, - { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, - { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, - { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, - }, - /* pred_R real : values for general and differential */ - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, - /* pred_R real : num dyn models for general and differential */ - 4, 4 - } -}; - -const ivas_freq_models_t ivas_arith_drct_r_consts[TOTAL_DRCT_QUANT_STRATS] = -{ - /* entry for 1 quantization points */ - { - /* drct real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* drct real : values for general and differential */ - {0},{ 0 }, - /* drct real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 7 quantization points */ - { /* drct real */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,988,1244,1568,1976,2489,3136,4983, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* drct real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, }, - }, - /* drct real : values for general and differential */ - { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, - /* drct real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 9 quantization points */ - { - /* drct real */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* drct real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, } - }, - /* drct real : values for general and differential */ - { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* drct real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 11 quantization points */ - { - /* drct real */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* drct real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* drct real : values for general and differential */ - { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* drct real : num dyn models for general and differential */ - 4, 4 - } -}; - -const ivas_freq_models_t ivas_arith_decd_r_consts[TOTAL_DECD_QUANT_STRATS] = -{ - /* entry for 1 quantization points */ - { - /* decd real */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd real differential */ - { - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - { 0,16384, }, - }, - /* decd real : values for general and differential */ - { 0 },{ 0 }, - /* decd real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 3 quantization points */ - { - /* decd real */ - { - { 0,11917,2978,1489, }, - { 0,8840,4419,3125, }, - { 0,4567,7250,4567, }, - { 0,5203,5978,5203, }, - }, - /* decd real differential */ - { - { 0,1356,13672,1356, }, - { 0,3166,10052,3166, }, - { 0,10984,3459,1941, }, - { 0,1941,3459,10984, }, - }, - /* decd real : values for general and differential */ - { 0,1,2 },{-1,0,1}, - /* decd real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 5 quantization points */ - { - /* decd real */ - { - { 0,11157,2788,1394,697,348, }, - { 0,7186,3592,2540,1796,1270, }, - { 0,2512,3166,5028,3166,2512, }, - { 0,3048,3267,3754,3267,3048, }, - }, - /* decd real differential */ - { - { 0,406,1289,12994,1289,406, }, - { 0,1460,2601,8262,2601,1460, }, - { 0,2707,8599,2707,1519,852, }, - { 0,852,1519,2707,8599,2707, }, - }, - /* decd real : values for general and differential */ - { 0,1,2,3,4 },{ -2,-1,0,1,2 }, - /* decd real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 7 quantization points */ - { - /* decd real */ - { - { 0,10983,2744,1372,686,343,171,85, }, - { 0,6573,3285,2322,1642,1161,821,580, }, - { 0,1603,2020,2546,4046,2546,2020,1603, }, - { 0,2111,2262,2425,2788,2425,2262,2111, }, - }, - /* decd real differential */ - { - { 0,125,399,1269,12798,1269,399,125, }, - { 0,744,1327,2365,7512,2365,1327,744, }, - { 0,1354,2413,7664,2413,1354,760,426, }, - { 0,426,760,1354,2413,7664,2413,1354, } - }, - /* decd real : values for general and differential */ - { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, - /* decd real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 9 quantization points */ - { /* decd real */ - { - { 0,10941,2734,1367,683,341,170,85,42,21, }, - { 0,6305,3150,2227,1575,1113,787,556,393,278, }, - { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, - { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, - }, - /* decd real differential */ - { - { 0,39,125,397,1263,12736,1263,397,125,39, }, - { 0,397,708,1262,2250,7150,2250,1262,708,397, }, - { 0,716,1276,2274,7225,2274,1276,716,402,225, }, - { 0,225,402,716,1276,2274,7225,2274,1276,716, } - }, - /* decd real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, - /* decd real : num dyn models for general and differential */ - 4, 4 - }, - /* entry for 11 quantization points */ - { - /* decd real */ - { - { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, - { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, - { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, - { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, - }, - /* decd real differential */ - { - { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, - { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, - { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, - { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, - }, - /* decd real : values for general and differential */ - { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, - /* decd real : num dyn models for general and differential */ - 4, 4 - } -}; - -const ivas_huff_models_t ivas_huff_pred_r_consts[TOTAL_PRED_QUANT_STRATS_HUFF] = -{ - /* entry for 1 quantization points for br_table_idx */ - {{{ 0 }}, {{ 0 }}}, - /* entry for 7 quantization points for br_table_idx */ - { - /* pred_R codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - /* pred_R differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, - }, - /* entry for 15 quantization points for br_table_idx */ - { - /* pred_r codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5, 4, 4 },{ -4, 4, 5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 }, - { 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 } }, - /* pred_r differential codebook */ - { { -7,4,2 },{ -6,4,3 },{ -5, 4, 4 },{ -4, 4, 5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 }, - { 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 } }, - }, - /* entry for 21 quantization points for br_table_idx=0 */ - { - /* pred_r codebook */ - { {-10,5,22},{-9,5,23},{-8,5,24},{-7,5,25},{-6,5,26}, { -5, 4, 0 },{ -4, 4, 1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 }, - { 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{6,5,27},{7,5,28},{8,5,29},{9,5,30},{10,5,31} }, - /* pred_r differential codebook */ - { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5, 4, 0 },{ -4, 4, 1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 }, - { 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 } }, - }, - - /* entry for 31 quantization points for br_table_idx>0 */ - { - /* pred_r codebook */ - { {-15,5,2},{-14,5,3},{-13,5,4},{-12,5,5},{-11,5,6}, { -10,5,7 },{ -9,5,8 },{ -8,5,9 }, - { -7,5,10 },{ -6,5,11 },{ -5, 5, 12 },{ -4, 5, 13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 }, - { 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 }, - { 8,5,24 },{ 9,5,25 },{ 10,5,26 },{11,5,27},{12,5,28},{13,5,29},{14,5,30},{15,5,31} }, - /* pred_r differential codebook */ - { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 }, - { -7,5,10 },{ -6,5,11 },{ -5, 5, 12 },{ -4, 5, 13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 }, - { 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 }, - { 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 } }, - }, - }; - - const ivas_huff_models_t ivas_huff_drct_r_consts[TOTAL_DRCT_QUANT_STRATS] = -{ - /* entry for 1 quantization points */ - {{{ 0 }}, {{ 0 }}}, - /* entry for 7 quantization points */ - { - /* drct_r codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, - /* drct_r differential codebook */ - { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, - }, - /* entry for 9 quantization points */ - { - /* drct_r codebook */ - { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, - /* drct_r differential codebook */ - { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, - }, - /* entry for 11 quantization points */ - { - /* drct_r codebook */ - { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, - /* drct_r differential codebook */ - { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, - }, -}; - -const ivas_huff_models_t ivas_huff_decd_r_consts[TOTAL_DECD_QUANT_STRATS] = -{ - /* entry for 1 quantization points */ - {{{ 0 }}, {{ 0 }}}, - /* entry for 3 quantization points */ - { - /* decd_r codebook */ - { { 0, 2, 2 },{ 1, 1, 0 },{ 2,2,3 } }, - /* decd_r differential codebook */ - { { -1, 2, 2 },{ 0, 1, 0 },{ 1,2,3 } }, - }, - /* entry for 5 quantization points */ - { - /* decd_r codebook */ - { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 } }, - /* decd_r differential codebook */ - { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 } }, - }, - /* entry for 7 quantization points */ - { - /* decd_r */ - { { 0, 3, 2 },{ 1, 3, 3 },{ 2,3,4 },{ 3,3,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 } }, - /* decd_r codebook differential codebook */ - { { -3, 3, 2 },{ -2, 3, 3 },{ -1,3,4 },{ 0,3,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, - }, - /* entry for 9 quantization points */ - { - /* decd_r codebook */ - { { 0, 4, 14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 } }, - /* decd_r differential codebook */ - { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, - }, - /* entry for 11 quantization points */ - { - /* decd_r codebook */ - { { 0, 4, 10 },{ 1, 4, 11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 } }, - /* decd_r differential codebook */ - { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, - }, -}; - -/* DTX quantization and bitstream constants */ - -const Word16 dtx_pd_real_q_levels[3][3] = { { 7,7,7 },{ 7,7,0 },{ 3,0,0 } }; -const Word16 dtx_pr_real_q_levels[3][3] = { { 9,9,9 },{ 9,7,9 },{ 9,5,7 } }; -const Word16 pr_pr_idx_pairs[3][3][2] = { { { 0, 0 },{ 0, 0 },{ 0, 0 } },{ { 0, 0 },{ 0, 0 },{ 0, 0 } },{ { 0, 0 },{ 1, 3 },{ 0, 0 } } }; -const Word16 pr_pd_idx_pairs[3][3][2] = { { { 1, 1 },{ 2, 2 },{ 3, 3 } },{ { 1, 1 },{ 3, 2 },{ 2, 0 } },{ { 2, 1 },{ 0, 0 },{ 0, 0 } } }; - -const Word16 remix_order_set[1][DIRAC_MAX_ANA_CHANS] = { /* WYZX --> WYXZ... */ - { 0, 1, 3, 2, 4, 5, 6, 7, 8, 9, 10 } -}; - -const Word16 HOA_keep_ind[IVAS_SPAR_MAX_FB_IN_CHAN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15}; -const Word16 HOA_keep_ind_spar[IVAS_SPAR_MAX_CH] = {0, 1, 2, 3, 4, 8, 9, 10, 10, 10, 10}; -const Word16 HOA_keep_ind_spar512[IVAS_SPAR_MAX_CH] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - - -/*----------------------------------------------------------------------* -* PCA ROM tables -*-----------------------------------------------------------------------*/ - -const Word32 ivas_pca_offset_index1[IVAS_PCA_N1 + 1] = -{ - 0, 1, 9, 61, 163, 359, 685, 1125, 1747, - 2519, 3521, 4713, 6183, 7883, 9809, 12093, 14633, 17575, - 20807, 24343, 28181, 32487, 37121, 42097, 47405, 53057, 59061, - 65421, 72137, 79205, 86625, 94415, 102345, 110629, 119263, 128017, - 137097, 146515, 156043, 165637, 175551, 185515, 195535, 205837, 216183, - 226545, 236911, 247273, 257619, 267921, 277941, 287905, 297819, 307413, - 316941, 326359, 335439, 344193, 352827, 361111, 369041, 376831, 384251, - 391319, 398035, 404395, 410399, 416051, 421359, 426335, 430969, 435275, - 439113, 442649, 445881, 448823, 451363, 453647, 455573, 457273, 458743, - 459935, 460937, 461709, 462331, 462771, 463097, 463293, 463395, 463447, - 463455, 463456 -}; - -const Word16 ivas_pca_offset_index2[2692] = -{ - 0, 1, 0, 1, 7, 8, 0, 1, 7, 19, - 33, 45, 51, 52, 0, 1, 9, 23, 41, 61, - 79, 93, 101, 102, 0, 1, 7, 21, 39, 61, - 85, 111, 135, 157, 175, 189, 195, 196, 0, 1, - 7, 19, 37, 59, 85, 115, 147, 179, 211, 241, - 267, 289, 307, 319, 325, 326, 0, 1, 7, 21, - 41, 65, 95, 127, 163, 201, 239, 277, 313, 345, - 375, 399, 419, 433, 439, 440, 0, 1, 7, 19, - 37, 61, 91, 125, 163, 203, 245, 289, 333, 377, - 419, 459, 497, 531, 561, 585, 603, 615, 621, 622, - 0, 1, 7, 21, 41, 67, 97, 133, 173, 217, - 263, 311, 361, 411, 461, 509, 555, 599, 639, 675, - 705, 731, 751, 765, 771, 772, 0, 1, 7, 19, - 37, 61, 91, 127, 167, 211, 259, 309, 363, 417, - 473, 529, 585, 639, 693, 743, 791, 835, 875, 911, - 941, 965, 983, 995, 1001, 1002, 0, 1, 7, 21, - 41, 67, 99, 135, 177, 223, 273, 327, 383, 443, - 503, 565, 627, 689, 749, 809, 865, 919, 969, 1015, - 1057, 1093, 1125, 1151, 1171, 1185, 1191, 1192, 0, 1, - 7, 19, 37, 61, 91, 127, 169, 215, 265, 319, - 377, 437, 501, 567, 633, 701, 769, 837, 903, 969, - 1033, 1093, 1151, 1205, 1255, 1301, 1343, 1379, 1409, 1433, - 1451, 1463, 1469, 1470, 0, 1, 7, 21, 41, 67, - 99, 137, 179, 227, 279, 335, 395, 459, 525, 595, - 667, 739, 813, 887, 961, 1033, 1105, 1175, 1241, 1305, - 1365, 1421, 1473, 1521, 1563, 1601, 1633, 1659, 1679, 1693, - 1699, 1700, 0, 1, 9, 23, 43, 69, 101, 139, - 183, 231, 285, 343, 405, 471, 541, 613, 689, 765, - 843, 923, 1003, 1083, 1161, 1237, 1313, 1385, 1455, 1521, - 1583, 1641, 1695, 1743, 1787, 1825, 1857, 1883, 1903, 1917, - 1925, 1926, 0, 1, 7, 21, 41, 67, 99, 137, - 179, 227, 281, 339, 401, 467, 537, 611, 687, 767, - 849, 931, 1015, 1099, 1185, 1269, 1353, 1435, 1517, 1597, - 1673, 1747, 1817, 1883, 1945, 2003, 2057, 2105, 2147, 2185, - 2217, 2243, 2263, 2277, 2283, 2284, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 285, 345, 409, 477, - 549, 625, 705, 787, 871, 957, 1045, 1135, 1225, 1315, - 1405, 1495, 1583, 1669, 1753, 1835, 1915, 1991, 2063, 2131, - 2195, 2255, 2309, 2359, 2403, 2441, 2473, 2499, 2519, 2533, - 2539, 2540, 0, 1, 7, 19, 39, 65, 97, 135, - 177, 225, 279, 337, 401, 469, 541, 617, 697, 781, - 867, 955, 1045, 1137, 1231, 1327, 1423, 1519, 1615, 1711, - 1805, 1897, 1987, 2075, 2161, 2245, 2325, 2401, 2473, 2541, - 2605, 2663, 2717, 2765, 2807, 2845, 2877, 2903, 2923, 2935, - 2941, 2942, 0, 1, 7, 21, 41, 67, 99, 137, - 181, 229, 283, 343, 407, 477, 551, 629, 711, 797, - 885, 977, 1071, 1167, 1265, 1365, 1465, 1565, 1667, 1767, - 1867, 1967, 2065, 2161, 2255, 2347, 2435, 2521, 2603, 2681, - 2755, 2825, 2889, 2949, 3003, 3051, 3095, 3133, 3165, 3191, - 3211, 3225, 3231, 3232, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 347, 413, 483, 559, 639, - 723, 811, 903, 997, 1093, 1193, 1295, 1399, 1503, 1609, - 1715, 1821, 1927, 2033, 2137, 2241, 2343, 2443, 2539, 2633, - 2725, 2813, 2897, 2977, 3053, 3123, 3189, 3249, 3305, 3355, - 3399, 3437, 3469, 3495, 3515, 3529, 3535, 3536, 0, 1, - 7, 21, 41, 67, 99, 137, 181, 231, 287, 349, - 415, 487, 563, 645, 731, 821, 915, 1011, 1111, 1213, - 1317, 1423, 1531, 1641, 1751, 1863, 1975, 2087, 2197, 2307, - 2415, 2521, 2625, 2727, 2827, 2923, 3017, 3107, 3193, 3275, - 3351, 3423, 3489, 3551, 3607, 3657, 3701, 3739, 3771, 3797, - 3817, 3831, 3837, 3838, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 285, 345, 411, 481, 557, 637, - 721, 809, 901, 997, 1097, 1199, 1305, 1413, 1523, 1635, - 1749, 1863, 1979, 2095, 2211, 2327, 2443, 2557, 2671, 2783, - 2893, 3001, 3107, 3209, 3309, 3405, 3497, 3585, 3669, 3749, - 3825, 3895, 3961, 4021, 4075, 4125, 4169, 4207, 4239, 4265, - 4285, 4299, 4305, 4306, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 347, 413, 485, 561, 643, - 729, 819, 913, 1011, 1113, 1217, 1325, 1435, 1547, 1663, - 1779, 1897, 2017, 2137, 2257, 2377, 2497, 2617, 2737, 2855, - 2971, 3087, 3199, 3309, 3417, 3521, 3623, 3721, 3815, 3905, - 3991, 4073, 4149, 4221, 4287, 4347, 4403, 4453, 4497, 4535, - 4567, 4593, 4613, 4627, 4633, 4634, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 415, 487, - 565, 647, 733, 825, 921, 1021, 1125, 1231, 1341, 1453, - 1569, 1687, 1807, 1929, 2051, 2175, 2299, 2425, 2551, 2677, - 2801, 2925, 3047, 3169, 3289, 3407, 3523, 3635, 3745, 3851, - 3955, 4055, 4151, 4243, 4329, 4411, 4489, 4561, 4627, 4689, - 4745, 4795, 4839, 4877, 4909, 4935, 4955, 4969, 4975, 4976, - 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, - 287, 349, 417, 489, 567, 649, 737, 829, 925, 1025, - 1129, 1237, 1349, 1463, 1581, 1701, 1823, 1947, 2073, 2201, - 2329, 2459, 2589, 2719, 2849, 2979, 3107, 3235, 3361, 3485, - 3607, 3727, 3845, 3959, 4071, 4179, 4283, 4383, 4479, 4571, - 4659, 4741, 4819, 4891, 4959, 5021, 5077, 5127, 5171, 5209, - 5241, 5267, 5287, 5301, 5307, 5308, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 417, 489, - 567, 651, 739, 831, 929, 1031, 1137, 1247, 1361, 1477, - 1597, 1719, 1843, 1969, 2097, 2227, 2359, 2491, 2625, 2759, - 2893, 3027, 3161, 3293, 3425, 3555, 3683, 3809, 3933, 4055, - 4175, 4291, 4405, 4515, 4621, 4723, 4821, 4913, 5001, 5085, - 5163, 5235, 5303, 5365, 5421, 5471, 5515, 5553, 5585, 5611, - 5631, 5645, 5651, 5652, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 569, 653, - 741, 835, 933, 1035, 1141, 1251, 1365, 1483, 1603, 1727, - 1853, 1983, 2115, 2249, 2383, 2519, 2657, 2795, 2933, 3071, - 3209, 3347, 3485, 3621, 3755, 3889, 4021, 4151, 4277, 4401, - 4521, 4639, 4753, 4863, 4969, 5071, 5169, 5263, 5351, 5435, - 5513, 5587, 5655, 5717, 5773, 5823, 5867, 5905, 5937, 5963, - 5983, 5997, 6003, 6004, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 569, 653, - 741, 835, 933, 1037, 1145, 1257, 1373, 1491, 1613, 1739, - 1867, 1997, 2131, 2267, 2405, 2543, 2683, 2825, 2967, 3109, - 3251, 3393, 3535, 3677, 3817, 3955, 4093, 4229, 4363, 4493, - 4621, 4747, 4869, 4987, 5103, 5215, 5323, 5427, 5525, 5619, - 5707, 5791, 5869, 5943, 6011, 6073, 6129, 6179, 6223, 6261, - 6293, 6319, 6339, 6353, 6359, 6360, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, - 569, 653, 743, 837, 935, 1039, 1147, 1259, 1375, 1495, - 1619, 1745, 1875, 2007, 2143, 2281, 2421, 2563, 2705, 2849, - 2993, 3139, 3285, 3431, 3577, 3723, 3867, 4011, 4153, 4295, - 4435, 4573, 4709, 4841, 4971, 5097, 5221, 5341, 5457, 5569, - 5677, 5781, 5879, 5973, 6063, 6147, 6225, 6299, 6367, 6429, - 6485, 6535, 6579, 6617, 6649, 6675, 6695, 6709, 6715, 6716, - 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, - 287, 349, 417, 491, 569, 653, 743, 837, 937, 1041, - 1149, 1261, 1377, 1497, 1621, 1749, 1879, 2013, 2149, 2287, - 2429, 2573, 2717, 2863, 3011, 3159, 3309, 3459, 3609, 3759, - 3909, 4057, 4205, 4351, 4495, 4639, 4781, 4919, 5055, 5189, - 5319, 5447, 5571, 5691, 5807, 5919, 6027, 6131, 6231, 6325, - 6415, 6499, 6577, 6651, 6719, 6781, 6837, 6887, 6931, 6969, - 7001, 7027, 7047, 7061, 7067, 7068, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, - 569, 653, 743, 837, 937, 1041, 1149, 1261, 1377, 1497, - 1621, 1749, 1881, 2015, 2153, 2293, 2435, 2579, 2725, 2873, - 3023, 3175, 3327, 3479, 3633, 3787, 3941, 4093, 4245, 4397, - 4547, 4695, 4841, 4985, 5127, 5267, 5405, 5539, 5671, 5799, - 5923, 6043, 6159, 6271, 6379, 6483, 6583, 6677, 6767, 6851, - 6929, 7003, 7071, 7133, 7189, 7239, 7283, 7321, 7353, 7379, - 7399, 7413, 7419, 7420, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 489, 567, 651, - 741, 835, 935, 1039, 1147, 1259, 1377, 1499, 1625, 1753, - 1885, 2021, 2159, 2301, 2445, 2591, 2739, 2889, 3041, 3195, - 3349, 3505, 3661, 3817, 3973, 4129, 4285, 4441, 4595, 4749, - 4901, 5051, 5199, 5345, 5489, 5631, 5769, 5905, 6037, 6165, - 6291, 6413, 6531, 6643, 6751, 6855, 6955, 7049, 7139, 7223, - 7301, 7373, 7441, 7503, 7559, 7609, 7653, 7691, 7723, 7749, - 7769, 7783, 7789, 7790, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, - 747, 843, 945, 1051, 1161, 1277, 1397, 1521, 1649, 1781, - 1915, 2053, 2195, 2339, 2485, 2635, 2787, 2941, 3095, 3251, - 3409, 3567, 3725, 3885, 4045, 4205, 4363, 4521, 4679, 4835, - 4989, 5143, 5295, 5445, 5591, 5735, 5877, 6015, 6149, 6281, - 6409, 6533, 6653, 6769, 6879, 6985, 7087, 7183, 7273, 7359, - 7439, 7513, 7581, 7643, 7699, 7749, 7793, 7831, 7863, 7889, - 7909, 7923, 7929, 7930, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, - 747, 843, 943, 1049, 1159, 1273, 1393, 1517, 1645, 1777, - 1913, 2051, 2193, 2337, 2485, 2635, 2787, 2941, 3097, 3255, - 3415, 3575, 3737, 3899, 4061, 4223, 4385, 4547, 4709, 4869, - 5029, 5187, 5343, 5497, 5649, 5799, 5947, 6091, 6233, 6371, - 6507, 6639, 6767, 6891, 7011, 7125, 7235, 7341, 7441, 7537, - 7627, 7713, 7793, 7867, 7935, 7997, 8053, 8103, 8147, 8185, - 8217, 8243, 8263, 8277, 8283, 8284, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, - 571, 655, 745, 841, 941, 1047, 1157, 1271, 1389, 1513, - 1641, 1773, 1907, 2045, 2187, 2331, 2479, 2629, 2783, 2939, - 3097, 3257, 3417, 3579, 3743, 3907, 4071, 4235, 4399, 4563, - 4727, 4891, 5055, 5217, 5377, 5537, 5695, 5851, 6005, 6155, - 6303, 6447, 6589, 6727, 6861, 6993, 7121, 7245, 7363, 7477, - 7587, 7693, 7793, 7889, 7979, 8063, 8143, 8217, 8285, 8347, - 8403, 8453, 8497, 8535, 8567, 8593, 8613, 8627, 8633, 8634, - 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, - 287, 349, 417, 491, 571, 657, 749, 845, 947, 1053, - 1165, 1281, 1401, 1527, 1657, 1791, 1929, 2069, 2213, 2361, - 2511, 2663, 2819, 2977, 3137, 3299, 3463, 3627, 3793, 3959, - 4125, 4293, 4461, 4629, 4795, 4961, 5127, 5291, 5455, 5617, - 5777, 5935, 6091, 6243, 6393, 6541, 6685, 6825, 6963, 7097, - 7227, 7353, 7473, 7589, 7701, 7807, 7909, 8005, 8097, 8183, - 8263, 8337, 8405, 8467, 8523, 8573, 8617, 8655, 8687, 8713, - 8733, 8747, 8753, 8754, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, - 747, 843, 943, 1049, 1159, 1275, 1395, 1519, 1647, 1779, - 1915, 2055, 2199, 2345, 2495, 2647, 2803, 2961, 3121, 3283, - 3447, 3613, 3779, 3947, 4115, 4285, 4455, 4625, 4795, 4965, - 5133, 5301, 5467, 5633, 5797, 5959, 6119, 6277, 6433, 6585, - 6735, 6881, 7025, 7165, 7301, 7433, 7561, 7685, 7805, 7921, - 8031, 8137, 8237, 8333, 8423, 8509, 8589, 8663, 8731, 8793, - 8849, 8899, 8943, 8981, 9013, 9039, 9059, 9073, 9079, 9080, - 0, 1, 7, 19, 39, 65, 97, 135, 179, 229, - 285, 347, 415, 489, 567, 651, 741, 835, 935, 1041, - 1151, 1265, 1385, 1509, 1637, 1769, 1905, 2045, 2189, 2335, - 2485, 2637, 2793, 2951, 3111, 3273, 3437, 3603, 3771, 3939, - 4109, 4279, 4451, 4623, 4795, 4967, 5139, 5309, 5479, 5647, - 5815, 5981, 6145, 6307, 6467, 6625, 6781, 6933, 7083, 7229, - 7373, 7513, 7649, 7781, 7909, 8033, 8153, 8267, 8377, 8483, - 8583, 8677, 8767, 8851, 8929, 9003, 9071, 9133, 9189, 9239, - 9283, 9321, 9353, 9379, 9399, 9411, 9417, 9418, 0, 1, - 7, 21, 41, 67, 99, 137, 181, 231, 287, 349, - 417, 491, 571, 657, 747, 843, 945, 1051, 1163, 1279, - 1399, 1525, 1655, 1789, 1927, 2069, 2213, 2361, 2513, 2667, - 2825, 2985, 3147, 3311, 3477, 3645, 3815, 3985, 4157, 4329, - 4503, 4677, 4851, 5025, 5199, 5371, 5543, 5713, 5883, 6051, - 6217, 6381, 6543, 6703, 6861, 7015, 7167, 7315, 7459, 7601, - 7739, 7873, 8003, 8129, 8249, 8365, 8477, 8583, 8685, 8781, - 8871, 8957, 9037, 9111, 9179, 9241, 9297, 9347, 9391, 9429, - 9461, 9487, 9507, 9521, 9527, 9528, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, - 571, 657, 749, 845, 947, 1055, 1167, 1285, 1407, 1533, - 1663, 1797, 1935, 2077, 2223, 2373, 2525, 2681, 2839, 3001, - 3165, 3331, 3499, 3669, 3839, 4011, 4185, 4359, 4533, 4709, - 4885, 5061, 5235, 5409, 5583, 5755, 5925, 6095, 6263, 6429, - 6593, 6755, 6913, 7069, 7221, 7371, 7517, 7659, 7797, 7931, - 8061, 8187, 8309, 8427, 8539, 8647, 8749, 8845, 8937, 9023, - 9103, 9177, 9245, 9307, 9363, 9413, 9457, 9495, 9527, 9553, - 9573, 9587, 9593, 9594, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 571, 655, - 745, 841, 941, 1047, 1157, 1273, 1393, 1517, 1647, 1781, - 1919, 2061, 2207, 2355, 2507, 2663, 2821, 2981, 3145, 3311, - 3479, 3649, 3821, 3993, 4167, 4341, 4517, 4693, 4869, 5045, - 5221, 5397, 5573, 5747, 5921, 6093, 6265, 6435, 6603, 6769, - 6933, 7093, 7251, 7407, 7559, 7707, 7853, 7995, 8133, 8267, - 8397, 8521, 8641, 8757, 8867, 8973, 9073, 9169, 9259, 9343, - 9423, 9497, 9565, 9627, 9683, 9733, 9777, 9815, 9847, 9873, - 9893, 9907, 9913, 9914, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, - 747, 843, 945, 1051, 1163, 1279, 1401, 1527, 1657, 1791, - 1929, 2071, 2217, 2367, 2519, 2675, 2835, 2997, 3161, 3327, - 3495, 3665, 3837, 4011, 4185, 4361, 4537, 4715, 4893, 5071, - 5249, 5427, 5603, 5779, 5953, 6127, 6299, 6469, 6637, 6803, - 6967, 7129, 7289, 7445, 7597, 7747, 7893, 8035, 8173, 8307, - 8437, 8563, 8685, 8801, 8913, 9019, 9121, 9217, 9307, 9393, - 9473, 9547, 9615, 9677, 9733, 9783, 9827, 9865, 9897, 9923, - 9943, 9957, 9963, 9964, 0, 1, 7, 21, 41, 67, - 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, - 749, 845, 947, 1055, 1167, 1285, 1407, 1533, 1663, 1799, - 1939, 2083, 2229, 2379, 2533, 2689, 2849, 3011, 3177, 3345, - 3515, 3687, 3861, 4035, 4211, 4387, 4565, 4743, 4921, 5099, - 5277, 5455, 5633, 5809, 5985, 6159, 6333, 6505, 6675, 6843, - 7009, 7171, 7331, 7487, 7641, 7791, 7937, 8081, 8221, 8357, - 8487, 8613, 8735, 8853, 8965, 9073, 9175, 9271, 9363, 9449, - 9529, 9603, 9671, 9733, 9789, 9839, 9883, 9921, 9953, 9979, - 9999, 10013, 10019, 10020, 0, 1, 7, 19, 39, 65, - 97, 135, 179, 229, 285, 347, 415, 489, 567, 651, - 741, 837, 937, 1043, 1153, 1269, 1389, 1513, 1643, 1777, - 1915, 2057, 2203, 2351, 2503, 2659, 2817, 2979, 3143, 3309, - 3477, 3647, 3819, 3993, 4169, 4345, 4523, 4701, 4881, 5061, - 5241, 5421, 5601, 5779, 5957, 6133, 6309, 6483, 6655, 6825, - 6993, 7159, 7323, 7485, 7643, 7799, 7951, 8099, 8245, 8387, - 8525, 8659, 8789, 8913, 9033, 9149, 9259, 9365, 9465, 9561, - 9651, 9735, 9813, 9887, 9955, 10017, 10073, 10123, 10167, 10205, - 10237, 10263, 10283, 10295, 10301, 10302, 0, 1, 7, 21, - 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, - 571, 655, 745, 841, 941, 1047, 1159, 1275, 1395, 1521, - 1651, 1785, 1923, 2065, 2211, 2361, 2513, 2669, 2829, 2991, - 3155, 3321, 3491, 3663, 3837, 4011, 4187, 4365, 4543, 4723, - 4903, 5083, 5263, 5443, 5623, 5803, 5981, 6159, 6335, 6509, - 6683, 6855, 7025, 7191, 7355, 7517, 7677, 7833, 7985, 8135, - 8281, 8423, 8561, 8695, 8825, 8951, 9071, 9187, 9299, 9405, - 9505, 9601, 9691, 9775, 9855, 9929, 9997, 10059, 10115, 10165, - 10209, 10247, 10279, 10305, 10325, 10339, 10345, 10346, 0, 1, - 7, 21, 41, 67, 99, 137, 181, 231, 287, 349, - 417, 491, 571, 655, 745, 841, 943, 1049, 1161, 1277, - 1397, 1523, 1653, 1787, 1925, 2067, 2213, 2363, 2517, 2673, - 2833, 2995, 3159, 3327, 3497, 3669, 3843, 4019, 4195, 4373, - 4551, 4731, 4911, 5091, 5271, 5451, 5631, 5811, 5989, 6167, - 6343, 6519, 6693, 6865, 7035, 7203, 7367, 7529, 7689, 7845, - 7999, 8149, 8295, 8437, 8575, 8709, 8839, 8965, 9085, 9201, - 9313, 9419, 9521, 9617, 9707, 9791, 9871, 9945, 10013, 10075, - 10131, 10181, 10225, 10263, 10295, 10321, 10341, 10355, 10361, 10362, - 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, - 287, 349, 417, 491, 571, 657, 747, 843, 945, 1051, - 1163, 1279, 1399, 1525, 1655, 1789, 1927, 2069, 2215, 2365, - 2519, 2675, 2835, 2997, 3161, 3329, 3499, 3671, 3845, 4021, - 4197, 4375, 4553, 4733, 4913, 5093, 5273, 5453, 5633, 5813, - 5991, 6169, 6345, 6521, 6695, 6867, 7037, 7205, 7369, 7531, - 7691, 7847, 8001, 8151, 8297, 8439, 8577, 8711, 8841, 8967, - 9087, 9203, 9315, 9421, 9523, 9619, 9709, 9795, 9875, 9949, - 10017, 10079, 10135, 10185, 10229, 10267, 10299, 10325, 10345, 10359, - 10365, 10366 -}; - -const Word16 ivas_pca_offset_n2[IVAS_PCA_N1] = -{ - 0, 2, 6, 14, 24, 38, 56, 76, 100, 126, 156, 188, - 224, 262, 302, 346, 392, 442, 494, 548, 604, 664, 726, 790, - 856, 924, 994, 1066, 1140, 1216, 1294, 1374, 1454, 1536, 1620, 1704, - 1790, 1878, 1966, 2054, 2144, 2234, 2324, 2416, 2508, 2600, 2692, 2784, - 2876, 2968, 3058, 3148, 3238, 3326, 3414, 3502, 3588, 3672, 3756, 3838, - 3918, 3998, 4076, 4152, 4226, 4298, 4368, 4436, 4502, 4566, 4628, 4688, - 4744, 4798, 4850, 4900, 4946, 4990, 5030, 5068, 5104, 5136, 5166, 5192, - 5216, 5236, 5254, 5268, 5278, 5286, 5290 -}; - -const Word16 ph1_q_n2_tbl[IVAS_PCA_N1][2] = { /* ph1_q : Q13, n2 : Q0 */ - { 0, 1 }, - { 286, 3 }, - { 572, 7 }, - { 858, 9 }, - { 1144, 13 }, - { 1430, 17 }, - { 1716, 19 }, - { 2002, 23 }, - { 2288, 25 }, - { 2574, 29 }, - { 2860, 31 }, - { 3146, 35 }, - { 3431, 37 }, - { 3717, 39 }, - { 4003, 43 }, - { 4289, 45 }, - { 4575, 49 }, - { 4861, 51 }, - { 5147, 53 }, - { 5433, 55 }, - { 5719, 59 }, - { 6005, 61 }, - { 6291, 63 }, - { 6577, 65 }, - { 6863, 67 }, - { 7149, 69 }, - { 7435, 71 }, - { 7721, 73 }, - { 8007, 75 }, - { 8293, 77 }, - { 8579, 79 }, - { 8865, 79 }, - { 9151, 81 }, - { 9437, 83 }, - { 9722, 83 }, - { 10008, 85 }, - { 10294, 87 }, - { 10580, 87 }, - { 10866, 87 }, - { 11152, 89 }, - { 11438, 89 }, - { 11724, 89 }, - { 12010, 91 }, - { 12296, 91 }, - { 12582, 91 }, - { 12868, 91 }, - { 13154, 91 }, - { 13440, 91 }, - { 13726, 91 }, - { 14012, 89 }, - { 14298, 89 }, - { 14584, 89 }, - { 14870, 87 }, - { 15156, 87 }, - { 15442, 87 }, - { 15728, 85 }, - { 16013, 83 }, - { 16299, 83 }, - { 16585, 81 }, - { 16871, 79 }, - { 17157, 79 }, - { 17443, 77 }, - { 17729, 75 }, - { 18015, 73 }, - { 18301, 71 }, - { 18587, 69 }, - { 18873, 67 }, - { 19159, 65 }, - { 19445, 63 }, - { 19731, 61 }, - { 20017, 59 }, - { 20303, 55 }, - { 20589, 53 }, - { 20875, 51 }, - { 21161, 49 }, - { 21447, 45 }, - { 21733, 43 }, - { 22019, 39 }, - { 22304, 37 }, - { 22590, 35 }, - { 22876, 31 }, - { 23162, 29 }, - { 23448, 25 }, - { 23734, 23 }, - { 24020, 19 }, - { 24306, 17 }, - { 24592, 13 }, - { 24878, 9 }, - { 25164, 7 }, - { 25450, 3 }, - { 25736, 1 } -}; - - -/*----------------------------------------------------------------------------------* - * Parametric MC ROM tables - *----------------------------------------------------------------------------------*/ - -const Word16 param_mc_band_grouping_20[20 + 1] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 23, 27, 33, 40, 52, 60 -}; - -const Word16 param_mc_coding_band_mapping_20[20] = -{ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -const Word16 param_mc_bands_coded_20[4] = -{ - 10, 14, 18, 20 -}; - -const Word16 param_mc_band_grouping_14[14 + 1] = -{ - 0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 28, 40, 60 -}; - -const Word16 param_mc_coding_band_mapping_14[14] = -{ - 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 -}; - -const Word16 param_mc_bands_coded_14[4] = -{ - 8, 11, 13, 14 -}; - -const Word16 param_mc_band_grouping_10[10 + 1] = -{ - 0, 1, 2, 3, 5, 7, 10, 14, 20, 40, 60 -}; - - -const Word16 param_mc_bands_coded_10[4] = -{ - 6, 8, 9, 10 -}; - -const Word16 param_mc_coding_band_mapping_10[10] = -{ - 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 -}; - -const Word16 Param_MC_index[MAX_CICP_CHANNELS] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 -}; - - -const Word32 ivas_param_mc_dmx_fac_CICP6_2tc_fx[12] = -{ - 2147483647,0,1518500224,1518500224,2147483647,0, /*Lt*/ - 0,2147483647,1518500224,1518500224,0,2147483647 /*Rt*/ -}; - -const Word32 ivas_param_mc_dmx_fac_CICP12_2tc_fx[16] = -{ - 2147483647,0,1518500224,1518500224,2147483647,0,2147483647,0, /*Lt*/ - 0,2147483647,1518500224,1518500224,0,2147483647,0,2147483647 /*Rt*/ -}; - -const Word32 ivas_param_mc_dmx_fac_CICP12_3tc_fx[24] = -{ - 2147483647,0,0,0,2147483647,0,2147483647,0, /*Lt*/ - 0,2147483647,0,0,0,2147483647,0,2147483647, /*Rt*/ - 0,0,2147483647,2147483647,0,0,0,0 /*Ct*/ -}; - -const Word32 ivas_param_mc_dmx_fac_CICP14_2tc_fx[16] = -{ - 2147483647,0,1518500224,1518500224,2147483647,0,2147483647,0, /*Lt*/ - 0,2147483647,1518500224,1518500224,0,2147483647,0,2147483647 /*Rt*/ -}; -const Word32 ivas_param_mc_dmx_fac_CICP14_3tc_fx[24] = -{ - 2147483647,0,0,0,2147483647,0,2147483647,0, /*Lt*/ - 0,2147483647,0,0,0,2147483647,0,2147483647, /*Rt*/ - 0,0,2147483647,2147483647,0,0,0,0 /*Ct*/ -}; - -const Word32 ivas_param_mc_dmx_fac_CICP16_3tc_fx[30] = -{ - 2147483647,0,0,0,2147483647,0,2147483647,0,2147483647,0, /*Lt*/ - 0,2147483647,0,0,0,2147483647,0,2147483647,0,2147483647, /*Rt*/ - 0,0,2147483647,2147483647,0,0,0,0,0,0 /*Ct*/ -}; - -const Word32 ivas_param_mc_dmx_fac_CICP19_3tc_fx[36] = -{ - 2147483647,0,0,0,2147483647,0,2147483647,0,2147483647,0,2147483647,0, /*Lt*/ - 0,2147483647,0,0,0,2147483647,0,2147483647,0,2147483647,0,2147483647, /*Rt*/ - 0,0,2147483647,2147483647,0,0,0,0,0,0,0,0 /*Ct*/ -}; - -const Word32 ivas_param_mc_dmx_fac_CICP19_4tc_fx[48] = -{ - 2147483647,0,1518500224,1518500224,2147483647,0,2147483647,0,0,0,0,0, /*Lht*/ - 0,2147483647,1518500224,1518500224,0,2147483647,0,2147483647,0,0,0,0, /*Rht*/ - 0,0,0,0,0,0,0,0,2147483647,0,2147483647,0, /*Lut*/ - 0,0,0,0,0,0,0,0,0,2147483647,0,2147483647 /*Rut*/ -}; - - -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP6_2tc_fx[6] = -{ - 12832, - 12832, - 6820, - 10607, - 10607, - 6820 -}; - -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP12_2tc_fx[8] = -{ - 11965, - 11965, - 6816, - 6877, - 6877, - 5619, - 5619, - 6816 -}; - -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP12_3tc_fx[8] = -{ - 16384, - 16384, - 9502, - 9502, - 6553, - 6553, - 32767, - 8192 -}; -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP14_2tc_fx[8] = -{ - 11936, - 11936, - 5993, - 6945, - 6945, - 8049, - 8049, - 6816 -}; - -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP14_3tc_fx[8] = -{ - 16291, - 16291, - 8257, - 8257, - 9666, - 9666, - 32767, - 8192 -}; - -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP16_3tc_fx[10] = -{ - 11141, - 11141, - 7209, - 7209, - 6553, - 6553, - 5898, - 5898, - 32767, - 8192 -}; - -//Q15 -const Word16 ivas_param_mc_ild_fac_CICP19_3tc_fx[12] = -{ - 9830, - 9830, - 5570, - 5570, - 3932, - 3932, - 6226, - 6226, - 6226, - 6226, - 32767, - 16384 -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP6_2tc = -{ - 5, - 6, - {0,1,2,4,5,3}, - {1,1,2,1,1,2}, - {{0},{1},{0,1},{0},{1},{0,1}} -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP12_2tc = -{ - 7, - 8, - {0,1,2,4,5,6,7,3}, - {1,1,2,1,1,1,1,2}, - {{0},{1},{0,1},{0},{1},{0},{1},{0,1}} -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP12_3tc = -{ - 6, - 8, - {0,1,4,5,6,7,2,3}, - {1,1,1,1,1,1,1,1}, - {{0},{1},{0},{1},{0},{1},{2},{2}} -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP14_2tc = -{ - 7, - 8, - {0,1,2,4,5,6,7,3}, - {1,1,2,1,1,1,1,2}, - {{0},{1},{0,1},{0},{1},{0},{1},{0,1}} -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP14_3tc = -{ - 6, - 8, - {0,1,4,5,6,7,2,3}, - {1,1,1,1,1,1,1,1}, - {{0},{1},{0},{1},{0},{1},{2},{2}} -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP16_3tc = -{ - 8, - 10, - {0,1,4,5,6,7,8,9,2,3}, - {1,1,1,1,1,1,1,1,1,1}, - {{0},{1},{0},{1},{0},{1},{0},{1},{2},{2}} -}; - -const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP19_3tc = -{ - 10, - 12, - {0,1,4,5,6,7,8,9,10,11,2,3}, - {1,1,1,1,1,1,1,1,1,1,1,1}, - {{0},{1},{0},{1},{0},{1},{0},{1},{0},{1},{2},{2}} -}; - -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP6_2tc = -{ - 4, - 5, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 2, 3 }} /* C/LFE */ -}; - -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP12_2tc = -{ - 6, - 7, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 2, 6 }, /* C/BLS */ - { 2, 7 }, /* C/BRS */ - { 2, 3 } /* C/LFE */ - } -}; - -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP12_3tc = -{ - 6, - 7, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 0, 6 }, /* L/BLS */ - { 1, 7 }, /* R/BRS */ - { 2, 3 } /* C/LFE */ - } -}; - -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP14_2tc = -{ - 6, - 7, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 2, 6 }, /* C/UFL */ - { 2, 7 }, /* C/UFR */ - { 2, 3 } /* C/LFE */ - } -}; -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP14_3tc = -{ - 6, - 7, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 0, 6 }, /* L/UFL */ - { 1, 7 }, /* R/UFR */ - { 2, 3 } /* C/LFE */ - } -}; - -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP16_3tc = -{ - 8, - 9, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 0, 6 }, /* L/UFL */ - { 1, 7 }, /* R/UFR */ - { 4, 8 }, /* LS/UBL */ - { 5, 9 }, /* RS/UBR */ - { 2, 3 } /* C/LFE */ - } -}; - -const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP19_3tc = -{ - 10, - 11, - { { 0, 4 }, /* L/LS */ - { 1, 5 }, /* R/RS */ - { 0, 2 }, /* L/C */ - { 1, 2 }, /* R/C */ - { 0, 6 }, /* L/LBS */ - { 1, 7 }, /* R/RBS */ - { 0, 8 }, /* L/UFL */ - { 1, 9 }, /* R/UFR */ - { 6, 10 }, /* LBS/UBL */ - { 7, 11 }, /* RBS/UBR */ - { 2, 3 } /* C/LFE */ - } -}; - -const PARAM_MC_CONF ivas_param_mc_conf[PARAM_MC_NUM_CONFIGS] = -{ - /* CICP6 48000 */ - { - MC_LS_SETUP_5_1, - 6, - 2, - IVAS_48k, - &ivas_param_mc_ild_mapping_CICP6_2tc, - &ivas_param_mc_icc_mapping_CICP6_2tc, - &ivas_param_mc_ild_fac_CICP6_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP6_2tc_fx[0] - }, - /* CICP6 64000 */ - { - MC_LS_SETUP_5_1, - 6, - 2, - IVAS_64k, - &ivas_param_mc_ild_mapping_CICP6_2tc, - &ivas_param_mc_icc_mapping_CICP6_2tc, - &ivas_param_mc_ild_fac_CICP6_2tc_fx[0], - & ivas_param_mc_dmx_fac_CICP6_2tc_fx[0] - }, - /* CICP6 80000 */ - { - MC_LS_SETUP_5_1, - 6, - 2, - IVAS_80k, - &ivas_param_mc_ild_mapping_CICP6_2tc, - &ivas_param_mc_icc_mapping_CICP6_2tc, - &ivas_param_mc_ild_fac_CICP6_2tc_fx[0], - & ivas_param_mc_dmx_fac_CICP6_2tc_fx[0] - }, - /* CICP12 48000 */ - { - MC_LS_SETUP_7_1, - 8, - 2, - IVAS_48k, - &ivas_param_mc_ild_mapping_CICP12_2tc, - &ivas_param_mc_icc_mapping_CICP12_2tc, - &ivas_param_mc_ild_fac_CICP12_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP12_2tc_fx[0] - }, - /* CICP12 64000 */ - { - MC_LS_SETUP_7_1, - 8, - 2, - IVAS_64k, - &ivas_param_mc_ild_mapping_CICP12_2tc, - &ivas_param_mc_icc_mapping_CICP12_2tc, - &ivas_param_mc_ild_fac_CICP12_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP12_2tc_fx[0] - }, - /* CICP12 80000 */ - { - MC_LS_SETUP_7_1, - 8, - 2, - IVAS_80k, - &ivas_param_mc_ild_mapping_CICP12_2tc, - &ivas_param_mc_icc_mapping_CICP12_2tc, - &ivas_param_mc_ild_fac_CICP12_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP12_2tc_fx[0], - }, - /* CICP12 96000 */ - { - MC_LS_SETUP_7_1, - 8, - 3, - IVAS_96k, - &ivas_param_mc_ild_mapping_CICP12_3tc, - &ivas_param_mc_icc_mapping_CICP12_3tc, - &ivas_param_mc_ild_fac_CICP12_3tc_fx[0], - &ivas_param_mc_dmx_fac_CICP12_3tc_fx[0] - }, - /* CICP14 48000 */ - { - MC_LS_SETUP_5_1_2, - 8, - 2, - IVAS_48k, - &ivas_param_mc_ild_mapping_CICP14_2tc, - &ivas_param_mc_icc_mapping_CICP14_2tc, - &ivas_param_mc_ild_fac_CICP14_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP14_2tc_fx[0] - }, - /* CICP14 64000 */ - { - MC_LS_SETUP_5_1_2, - 8, - 2, - IVAS_64k, - &ivas_param_mc_ild_mapping_CICP14_2tc, - &ivas_param_mc_icc_mapping_CICP14_2tc, - &ivas_param_mc_ild_fac_CICP14_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP14_2tc_fx[0] - }, - /* CICP14 80000 */ - { - MC_LS_SETUP_5_1_2, - 8, - 2, - IVAS_80k, - &ivas_param_mc_ild_mapping_CICP14_2tc, - &ivas_param_mc_icc_mapping_CICP14_2tc, - &ivas_param_mc_ild_fac_CICP14_2tc_fx[0], - &ivas_param_mc_dmx_fac_CICP14_2tc_fx[0] - }, - /* CICP14 96000 */ - { - MC_LS_SETUP_5_1_2, - 8, - 3, - IVAS_96k, - &ivas_param_mc_ild_mapping_CICP14_3tc, - &ivas_param_mc_icc_mapping_CICP14_3tc, - &ivas_param_mc_ild_fac_CICP14_3tc_fx[0], - &ivas_param_mc_dmx_fac_CICP14_3tc_fx[0] - }, - /* CICP16 96000 */ - { - MC_LS_SETUP_5_1_4, - 10, - 3, - IVAS_96k, - &ivas_param_mc_ild_mapping_CICP16_3tc, - &ivas_param_mc_icc_mapping_CICP16_3tc, - &ivas_param_mc_ild_fac_CICP16_3tc_fx[0], - &ivas_param_mc_dmx_fac_CICP16_3tc_fx[0] - }, - /* CICP16 128000 */ - { - MC_LS_SETUP_5_1_4, - 10, - 3, - IVAS_128k, - &ivas_param_mc_ild_mapping_CICP16_3tc, - &ivas_param_mc_icc_mapping_CICP16_3tc, - &ivas_param_mc_ild_fac_CICP16_3tc_fx[0], - &ivas_param_mc_dmx_fac_CICP16_3tc_fx[0] - }, - /* CICP19 128000 */ +/*----------------------------------------------------------------------------------* + * IVAS limiter table + *----------------------------------------------------------------------------------*/ +const Word32 release_cnst_table[4][201] = // Q31 { - MC_LS_SETUP_7_1_4, - 12, - 3, - IVAS_128k, - &ivas_param_mc_ild_mapping_CICP19_3tc, - &ivas_param_mc_icc_mapping_CICP19_3tc, - &ivas_param_mc_ild_fac_CICP19_3tc_fx[0], - &ivas_param_mc_dmx_fac_CICP19_3tc_fx[0] - } -}; - - -/* Alphabet for delta coding for the ICCs in Parametric MC processing */ -const UWord16 ivas_param_mc_cum_freq_icc_cicp6_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = -{ - 0, 24, 224, 20873, 42384, 51699, 57122, 60572, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_cicp6_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 24, 200, 20649, 21511, 9315, 5423, 3450, 4963 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 0, 4, 9, 124, 447, 1311, 4453, 18116, 48636, 60573, 63692, 64746, 65327, 65531, 65534, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1] = -{ - 4, 5, 115, 323, 864, 3142, 13663, 30520, 11937, 3119, 1054, 581, 204, 3, 1 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_cicp12_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = -{ - 0, 30, 848, 26611, 47846, 57358, 61679, 63237, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_cicp12_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 30, 818, 25763, 21235, 9512, 4321, 1558, 2298 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 0, 2, 7, 53, 243, 979, 3994, 16732, 49642, 61343, 64331, 65158, 65438, 65532, 65534, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1] = -{ - 2, 5, 46, 190, 736, 3015, 12738, 32910, 11701, 2988, 827, 280, 94, 2, 1 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_cicp14_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = -{ - 0, 46, 826, 27798, 49552, 58447, 62046, 63284, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_cicp14_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER ]={ - 46, 780, 26972, 21754, 8895, 3599, 1238, 2251 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_delta_cicp14_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 0, 3, 8, 36, 172, 763, 3436, 15845, 50168, 62005, 64676, 65298, 65481, 65533, 65534, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_delta_cicp14_48_16bits[2* PARAM_MC_SZ_ICC_QUANTIZER - 1] = -{ - 3, 5, 28, 136, 591, 2673, 12409, 34323, 11837, 2671, 622, 183, 52, 1, 1 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_combined_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = -{ - 0, 34, 552, 24717, 45819, 54772, 59054, 61166, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_combined_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 34, 518, 24165, 21102, 8953, 4282, 2112, 4369 -}; - -const UWord16 ivas_param_mc_cum_freq_icc_delta_combined_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = -{ - 0, 3, 7, 74, 304, 1009, 3870, 16502, 49834, 61384, 64217, 65020, 65369, 65531, 65534, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_icc_delta_combined_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1] = -{ - 3, 4, 67, 230, 705, 2861, 12632, 33332, 11550, 2833, 803, 349, 162, 3, 1 -}; - -const UWord16 ivas_param_mc_cum_freq_ild_cicp6_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS + 1] = -{ - 0, 1092, 5574, 8315, 10652, 13875, 19656, 27664, 36284, 47058, 56251, 62579, 65118, 65462, 65513, 65532, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_ild_cicp6_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = -{ - 1092, 4482, 2741, 2337, 3223, 5781, 8008, 8620, 10774, 9193, 6328, 2539, 344, 51, 19, 3 -}; - -const UWord16 ivas_param_mc_cum_freq_ild_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = -{ - 0, 1, 2, 3, 5, 38, 146, 352, 638, 997, 1559, 2323, 3570, 5859, 10556, 21075, 44682, 55617, 60408, 62739, 63833, 64443, 64809, 65074, 65279, 65400, 65484, 65531, 65532, 65533, 65534, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_ild_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = -{ - 1, 1, 1, 2, 33, 108, 206, 286, 359, 562, 764, 1247, 2289, 4697, 10519, 23607, 10935, 4791, 2331, 1094, 610, 366, 265, 205, 121, 84, 47, 1, 1, 1, 1 -}; - -const UWord16 ivas_param_mc_cum_freq_ild_cicp12_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS + 1] = -{ - 0, 967, 6335, 9941, 12837, 16652, 22416, 29814, 38807, 48497, 57184, 62661, 64916, 65466, 65514, 65530, 65535 -}; - -const UWord16 ivas_param_mc_sym_freq_ild_cicp12_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = -{ - 967, 5368, 3606, 2896, 3815, 5764, 7398, 8993, 9690, 8687, 5477, 2255, 550, 48, 16, 5 -}; + { + 1913946752, + 1919716352, + 1925351680, + 1930855552, + 1936230784, + 1941479808, + 1946605312, + 1951609728, + 1956495744, + 1961265792, + 1965922304, + 1970467584, + 1974904320, + 1979234560, + 1983460736, + 1987585024, + 1991609856, + 1995537280, + 1999369344, + 2003108480, + 2006756480, + 2010315520, + 2013787520, + 2017174528, + 2020478464, + 2023701248, + 2026844672, + 2029910656, + 2032900992, + 2035817344, + 2038661376, + 2041435008, + 2044139648, + 2046777088, + 2049348864, + 2051856384, + 2054301440, + 2056685312, + 2059009536, + 2061275520, + 2063484672, + 2065638272, + 2067737856, + 2069784448, + 2071779584, + 2073724416, + 2075620096, + 2077467904, + 2079268992, + 2081024512, + 2082735488, + 2084403200, + 2086028416, + 2087612544, + 2089156352, + 2090660864, + 2092127104, + 2093555968, + 2094948480, + 2096305408, + 2097627776, + 2098916352, + 2100172032, + 2101395584, + 2102587776, + 2103749504, + 2104881408, + 2105984384, + 2107059072, + 2108106112, + 2109126400, + 2110120448, + 2111088896, + 2112032512, + 2112951808, + 2113847552, + 2114720128, + 2115570304, + 2116398592, + 2117205504, + 2117991552, + 2118757504, + 2119503616, + 2120230400, + 2120938496, + 2121628288, + 2122300288, + 2122954880, + 2123592576, + 2124213760, + 2124818944, + 2125408384, + 2125982592, + 2126541952, + 2127086848, + 2127617664, + 2128134656, + 2128638336, + 2129128832, + 2129606784, + 2130072192, + 2130525568, + 2130967296, + 2131397376, + 2131816448, + 2132224640, + 2132622080, + 2133009408, + 2133386496, + 2133753856, + 2134111744, + 2134460288, + 2134799744, + 2135130368, + 2135452416, + 2135766144, + 2136071680, + 2136369152, + 2136659072, + 2136941312, + 2137216256, + 2137484160, + 2137744896, + 2137998976, + 2138246400, + 2138487424, + 2138722176, + 2138950656, + 2139173376, + 2139390208, + 2139601408, + 2139807104, + 2140007424, + 2140202624, + 2140392576, + 2140577664, + 2140758016, + 2140933504, + 2141104512, + 2141271040, + 2141433216, + 2141591168, + 2141745024, + 2141894912, + 2142040832, + 2142182912, + 2142321408, + 2142456192, + 2142587392, + 2142715264, + 2142839808, + 2142961152, + 2143079296, + 2143194240, + 2143306240, + 2143415424, + 2143521664, + 2143625216, + 2143725952, + 2143824128, + 2143919744, + 2144012800, + 2144103424, + 2144191744, + 2144277760, + 2144361472, + 2144443136, + 2144522496, + 2144599936, + 2144675200, + 2144748544, + 2144820096, + 2144889600, + 2144957440, + 2145023488, + 2145087744, + 2145150336, + 2145211264, + 2145270656, + 2145328512, + 2145384832, + 2145439616, + 2145493120, + 2145545088, + 2145595776, + 2145645056, + 2145693184, + 2145739904, + 2145785472, + 2145829888, + 2145873152, + 2145915136, + 2145956224, + 2145996032, + 2146034944, + 2146072832, + 2146109696, + 2146145664, + 2146180608, + 2146214656, + 2146247808, + }, + { + 2027355264, + 2030408704, + 2033386624, + 2036290944, + 2039123328, + 2041885440, + 2044578944, + 2047205376, + 2049766528, + 2052263680, + 2054698496, + 2057072384, + 2059387008, + 2061643520, + 2063843328, + 2065987968, + 2068078720, + 2070116864, + 2072103552, + 2074040192, + 2075927936, + 2077767936, + 2079561472, + 2081309568, + 2083013376, + 2084673920, + 2086292352, + 2087869696, + 2089406976, + 2090905216, + 2092365184, + 2093788032, + 2095174528, + 2096525824, + 2097842432, + 2099125632, + 2100375808, + 2101594240, + 2102781312, + 2103938048, + 2105065216, + 2106163456, + 2107233536, + 2108276096, + 2109292032, + 2110281728, + 2111246080, + 2112185728, + 2113101056, + 2113992960, + 2114861824, + 2115708288, + 2116532992, + 2117336448, + 2118119168, + 2118881792, + 2119624704, + 2120348416, + 2121053440, + 2121740288, + 2122409344, + 2123061120, + 2123696128, + 2124314624, + 2124917120, + 2125504128, + 2126075776, + 2126632832, + 2127175296, + 2127703808, + 2128218624, + 2128720000, + 2129208448, + 2129684352, + 2130147712, + 2130599168, + 2131038976, + 2131467264, + 2131884416, + 2132290816, + 2132686592, + 2133072256, + 2133447680, + 2133813504, + 2134169856, + 2134516864, + 2134854784, + 2135184000, + 2135504640, + 2135816960, + 2136121216, + 2136417536, + 2136706048, + 2136987136, + 2137260928, + 2137527552, + 2137787264, + 2138040192, + 2138286592, + 2138526464, + 2138760192, + 2138987776, + 2139209472, + 2139425408, + 2139635712, + 2139840512, + 2140039936, + 2140234240, + 2140423424, + 2140607744, + 2140787200, + 2140962048, + 2141132288, + 2141298048, + 2141459584, + 2141616896, + 2141769984, + 2141919232, + 2142064512, + 2142205952, + 2142343808, + 2142478080, + 2142608768, + 2142736128, + 2142860032, + 2142980864, + 2143098368, + 2143212928, + 2143324544, + 2143433088, + 2143538944, + 2143641984, + 2143742336, + 2143840000, + 2143935232, + 2144027904, + 2144118144, + 2144206080, + 2144291712, + 2144375168, + 2144456320, + 2144535424, + 2144612480, + 2144687488, + 2144760448, + 2144831616, + 2144900992, + 2144968448, + 2145034112, + 2145098112, + 2145160448, + 2145221248, + 2145280256, + 2145337856, + 2145393920, + 2145448576, + 2145501696, + 2145553536, + 2145603968, + 2145653120, + 2145700992, + 2145747456, + 2145792896, + 2145837056, + 2145880064, + 2145922048, + 2145962880, + 2146002560, + 2146041344, + 2146078976, + 2146115712, + 2146151424, + 2146186240, + 2146220160, + 2146253184, + 2146285312, + 2146316672, + 2146347136, + 2146376832, + 2146405760, + 2146433920, + 2146461440, + 2146488192, + 2146514176, + 2146539520, + 2146564224, + 2146588160, + 2146611584, + 2146634368, + 2146656640, + 2146678272, + 2146699264, + 2146719744, + 2146739712, + 2146759168, + 2146778112, + 2146796544, + 2146814464, + 2146832000, + 2146849024, + 2146865664, + }, + { + 2086555136, + 2088125824, + 2089656576, + 2091148416, + 2092602240, + 2094018944, + 2095399680, + 2096745088, + 2098056192, + 2099333888, + 2100578816, + 2101792000, + 2102974080, + 2104125824, + 2105248128, + 2106341760, + 2107407232, + 2108445440, + 2109456896, + 2110442496, + 2111402624, + 2112338176, + 2113249664, + 2114137728, + 2115002880, + 2115845760, + 2116666880, + 2117466880, + 2118246272, + 2119005568, + 2119745280, + 2120465920, + 2121167872, + 2121851776, + 2122517888, + 2123166976, + 2123799168, + 2124414976, + 2125014912, + 2125599360, + 2126168704, + 2126723200, + 2127263360, + 2127789568, + 2128302208, + 2128801408, + 2129287808, + 2129761536, + 2130222976, + 2130672512, + 2131110272, + 2131536768, + 2131952128, + 2132356736, + 2132750848, + 2133134720, + 2133508736, + 2133872896, + 2134227584, + 2134573184, + 2134909696, + 2135237504, + 2135556736, + 2135867648, + 2136170624, + 2136465536, + 2136752896, + 2137032832, + 2137305344, + 2137570816, + 2137829376, + 2138081280, + 2138326528, + 2138565504, + 2138798080, + 2139024768, + 2139245440, + 2139460480, + 2139669888, + 2139873792, + 2140072320, + 2140265856, + 2140454144, + 2140637696, + 2140816384, + 2140990464, + 2141159936, + 2141325056, + 2141485824, + 2141642368, + 2141794944, + 2141943424, + 2142088064, + 2142228992, + 2142366208, + 2142499840, + 2142630016, + 2142756736, + 2142880128, + 2143000448, + 2143117440, + 2143231488, + 2143342592, + 2143450752, + 2143556096, + 2143658624, + 2143758592, + 2143855872, + 2143950592, + 2144043008, + 2144132864, + 2144220416, + 2144305664, + 2144388608, + 2144469504, + 2144548224, + 2144624896, + 2144699648, + 2144772352, + 2144843264, + 2144912256, + 2144979328, + 2145044864, + 2145108480, + 2145170560, + 2145231104, + 2145289856, + 2145347200, + 2145403008, + 2145457408, + 2145510400, + 2145561984, + 2145612160, + 2145661056, + 2145708672, + 2145755136, + 2145800192, + 2145844224, + 2145887104, + 2145928832, + 2145969408, + 2146008960, + 2146047616, + 2146085120, + 2146121600, + 2146157184, + 2146191872, + 2146225664, + 2146258560, + 2146290560, + 2146321792, + 2146352128, + 2146381696, + 2146410496, + 2146438528, + 2146465920, + 2146492416, + 2146518400, + 2146543616, + 2146568192, + 2146592128, + 2146615424, + 2146638080, + 2146660224, + 2146681728, + 2146702720, + 2146723072, + 2146743040, + 2146762368, + 2146781184, + 2146799616, + 2146817408, + 2146834816, + 2146851840, + 2146868352, + 2146884352, + 2146900096, + 2146915328, + 2146930176, + 2146944640, + 2146958720, + 2146972416, + 2146985856, + 2146998784, + 2147011456, + 2147023872, + 2147035904, + 2147047552, + 2147058944, + 2147070080, + 2147080832, + 2147091456, + 2147101696, + 2147111680, + 2147121408, + 2147130880, + 2147140096, + 2147149056, + 2147157760, + 2147166336, + 2147174656, + }, + { + 2106670080, + 2107727232, + 2108757120, + 2109760640, + 2110738432, + 2111691008, + 2112619136, + 2113523328, + 2114404352, + 2115262592, + 2116098816, + 2116913408, + 2117707136, + 2118480256, + 2119233536, + 2119967360, + 2120682240, + 2121378688, + 2122057088, + 2122717952, + 2123361792, + 2123988992, + 2124599936, + 2125195136, + 2125774848, + 2126339584, + 2126889728, + 2127425536, + 2127947520, + 2128456064, + 2128951296, + 2129433856, + 2129903744, + 2130361600, + 2130807424, + 2131241728, + 2131664768, + 2132076928, + 2132478208, + 2132869248, + 2133250048, + 2133620992, + 2133982208, + 2134334080, + 2134676864, + 2135010688, + 2135335936, + 2135652608, + 2135961088, + 2136261504, + 2136554112, + 2136839168, + 2137116800, + 2137387136, + 2137650560, + 2137907072, + 2138156928, + 2138400256, + 2138637184, + 2138867968, + 2139092864, + 2139311744, + 2139524992, + 2139732736, + 2139934976, + 2140131968, + 2140323840, + 2140510720, + 2140692736, + 2140870016, + 2141042688, + 2141210752, + 2141374592, + 2141534080, + 2141689344, + 2141840640, + 2141987968, + 2142131456, + 2142271232, + 2142407424, + 2142539904, + 2142669056, + 2142794752, + 2142917248, + 2143036544, + 2143152640, + 2143265792, + 2143375872, + 2143483264, + 2143587712, + 2143689472, + 2143788544, + 2143885056, + 2143979136, + 2144070656, + 2144159872, + 2144246656, + 2144331264, + 2144413568, + 2144493824, + 2144571904, + 2144647936, + 2144722048, + 2144794240, + 2144864512, + 2144932864, + 2144999552, + 2145064448, + 2145127680, + 2145189248, + 2145249152, + 2145307520, + 2145364480, + 2145419776, + 2145473792, + 2145526272, + 2145577472, + 2145627264, + 2145675776, + 2145723008, + 2145768960, + 2145813760, + 2145857408, + 2145899904, + 2145941376, + 2145981696, + 2146020864, + 2146059136, + 2146096384, + 2146132608, + 2146167936, + 2146202368, + 2146235776, + 2146268416, + 2146300160, + 2146331136, + 2146361216, + 2146390528, + 2146419200, + 2146446976, + 2146474112, + 2146500480, + 2146526208, + 2146551168, + 2146575488, + 2146599296, + 2146622464, + 2146644864, + 2146666880, + 2146688128, + 2146708992, + 2146729216, + 2146748928, + 2146768128, + 2146786816, + 2146805120, + 2146822784, + 2146840064, + 2146856960, + 2146873344, + 2146889216, + 2146904832, + 2146919936, + 2146934656, + 2146948992, + 2146962944, + 2146976640, + 2146989824, + 2147002752, + 2147015296, + 2147027584, + 2147039488, + 2147051136, + 2147062400, + 2147073408, + 2147084160, + 2147094528, + 2147104768, + 2147114624, + 2147124352, + 2147133696, + 2147142912, + 2147151744, + 2147160448, + 2147168896, + 2147177088, + 2147185152, + 2147192960, + 2147200512, + 2147207936, + 2147215104, + 2147222144, + 2147229056, + 2147235712, + 2147242112, + 2147248384, + 2147254656, + 2147260544, + 2147266432, + 2147272064, + 2147277568, + }, -const UWord16 ivas_param_mc_cum_freq_ild_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = -{ - 0, 1, 2, 3, 5, 18, 61, 149, 320, 592, 1083, 1793, 2974, 5257, 10133, 21274, 44342, 55891, 60895, 63174, 64244, 64793, 65100, 65287, 65406, 65477, 65517, 65531, 65532, 65533, 65534, 65535 -}; -const UWord16 ivas_param_mc_sym_freq_ild_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = -{ - 1, 1, 1, 2, 13, 43, 88, 171, 272, 491, 710, 1181, 2283, 4876, 11141, 23068, 11549, 5004, 2279, 1070, 549, 307, 187, 119, 71, 40, 14, 1, 1, 1, 1 -}; + }; -const UWord16 ivas_param_mc_cum_freq_ild_cicp14_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS + 1] = -{ - 0, 229, 7068, 10910, 13856, 17467, 22629, 29174, 36906, 46558, 55579, 61802, 65222, 65505, 65527, 65534, 65535 -}; +/*------------------------------------------------------------------------- + * DFT Stereo ROM tables + *------------------------------------------------------------------------*/ -const UWord16 ivas_param_mc_sym_freq_ild_cicp14_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +/*4xERB scale: max of 14 bands*/ +const Word16 dft_band_limits_erb4[STEREO_DFT_ERB4_BANDS] = { - 229, 6839, 3842, 2946, 3611, 5162, 6545, 7732, 9652, 9021, 6223, 3420, 283, 22, 7, 1 + 1, 3, 5, 10, 18, 26, 41, 56, 84, 132, 214, 342, 470, 601 }; -const UWord16 ivas_param_mc_cum_freq_ild_delta_cicp14_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +/*8xERB scale: max of 8 bands*/ +const Word16 dft_band_limits_erb8[STEREO_DFT_ERB8_BANDS] = { - 0, 1, 2, 3, 4, 12, 56, 153, 278, 475, 856, 1430, 2489, 4723, 9580, 20685, 45423, 56274, 60948, 63097, 64128, 64679, 65002, 65208, 65348, 65445, 65517, 65531, 65532, 65533, 65534, 65535 + 1, 5, 18, 41, 84, 214, 470, 601 }; -const UWord16 ivas_param_mc_sym_freq_ild_delta_cicp14_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = -{ - 1, 1, 1, 1, 8, 44, 97, 125, 197, 381, 574, 1059, 2234, 4857, 11105, 24738, 10851, 4674, 2149, 1031, 551, 323, 206, 140, 97, 72, 14, 1, 1, 1, 1 -}; -const UWord16 ivas_param_mc_cum_freq_ild_combined_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS+1] = +const Word16 dft_band_ipd[3][4] = { - 0, 1453, 8326, 12221, 15164, 18764, 24177, 31297, 39520, 49154, 57135, 62460, 64821, 65468, 65514, 65530, 65535 + {0,8,10,13}, + {0,5,6,8}, + {0,2,3,4} }; -const UWord16 ivas_param_mc_sym_freq_ild_combined_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +const Word16 dft_band_res_cod[3][4] = { - 1453, 6873, 3895, 2943, 3600, 5413, 7120, 8223, 9634, 7981, 5325, 2361, 647, 46, 16, 5 + {0,8,10,11}, + {0,5,6,7}, + {0,5,6,7} }; -const UWord16 ivas_param_mc_cum_freq_ild_delta_combined_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +// Q31 +const Word32 dft_res_gains_q_Q31[][2] = { - 0, 1, 2, 3, 5, 29, 98, 220, 414, 699, 1186, 1876, 3049, 5304, 10013, 20612, 45247, 56109, 60818, 63022, 64081, 64647, 64977, 65198, 65348, 65443, 65502, 65530, 65532, 65533, 65534, 65535 -}; + /* quantization points for joint quantization of prediction gain and residual energy */ -const UWord16 ivas_param_mc_sym_freq_ild_delta_combined_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = -{ - 1, 1, 1, 2, 24, 69, 122, 194, 285, 487, 690, 1173, 2255, 4709, 10599, 24635, 10862, 4709, 2204, 1059, 566, 330, 221, 150, 95, 59, 28, 2, 1, 1, 1 -}; + /* column 1 (|ILD| = 0): */ + {0, 0 }, + {0, 251216928 }, + {0, 487459456 }, + {0, 731632640 }, + {0, 997611392 }, + {0, 1299397248 }, + {0, 1666984192 }, + {0, 2147483647 }, + /* column 2 (|ILD| = 2): */ + {246151024, 0 }, + {249475328, 247871152 }, + {258660112, 480729248 }, + {274304544, 720918848 }, + {298427200, 981720000 }, + {334663840, 1276185088 }, + {391374592, 1632160640 }, + {485919712, 2091786496 }, -/*----------------------------------------------------------------------------------* - * MASA ROM tables - *----------------------------------------------------------------------------------*/ + /* column 3 (|ILD| = 4): */ + {485919712, 0 }, + {492224736, 238188144 }, + {509610752, 461283776 }, + {539117184, 690072384 }, + {584326016, 936189056 }, + {651608832, 1210182144 }, + {755411712, 1534299776 }, + {924504576, 1938292992 }, -const Word64 diffuseness_reconstructions_hr_fx[HR_MASA_ER_LEVELS] = { /* Q62 */ - 0, - 65865144550293504, - 138485688541642752, - 239816680157478912, - 355502895585558528, - 485544334825881600, - 667940119734386688, - 902690250311073792, - 1225260573621485568, - 1635651089665622016, - 2011983133527769088, - 2354256705207926784, - 2741003323208368128, - 3172222987529093120, - 3693796119373938688, - 4305722718742904832, -}; + /* column 4 (|ILD| = 6): */ + {713563712, 0 }, + {722237376, 223142880 }, + {746085184, 431184640 }, + {786311872, 642617280 }, + {847364864, 866812416 }, + {936938496, 1111020032 }, + {1072199936, 1390431232 }, + {1285225984, 1720430720 }, -const Word32 diffuseness_thresholds_hr_fx[HR_MASA_ER_LEVELS + 1] = { /* Q30 */ - 0, - 10223616, - 20447232, - 44040192, - 67633152, - 97910784, - 128188416, - 182845440, - 237502464, - 333053952, - 428605440, - 508297216, - 587988992, - 688390144, - 788791296, - 931266560, - MAX_32 /* out-of-range large value to make searching easier */ -}; + /* column 5 (|ILD| = 8): */ + {924504576, 0 }, + {934784576, 204139792 }, + {962942400, 393358880 }, + {1010083968, 583482048 }, + {1080789888, 781462848 }, + {1182728704, 991308544 }, + {1332741248, 1221608960 }, + {1559902080, 1475937536 }, -const Word16 bits_direction_masa[DIRAC_DIFFUSE_LEVELS] = -{ - 11, - 11, - 10, - 9, - 7, - 6, - 5, - 3 -}; + /* column 6 (|ILD| = 10): */ + {1115604864, 0 }, + {1126709504, 182744416 }, + {1156997632, 351025536 }, + {1207276672, 517958016 }, + {1281710592, 688294272 }, + {1387005952, 863412992 }, + {1537761536, 1046870336 }, + {1757032448, 1234717184 }, + /* column 7 (|ILD| = 13): */ + {1361843968, 0 }, + {1372924928, 149366080 }, + {1402942464, 285507936 }, + {1452130560, 417893888 }, + {1523515136, 548787328 }, + {1621670144, 677135936 }, + {1756740352, 802203264 }, + {1942499840, 915633344 }, -const Word16 len_cb_dct0_masa[DIRAC_DIFFUSE_LEVELS] = { 7, 6, 5, 4, 4, 4, 3, 2 }; + /* column 8 (|ILD| = 16): */ + {1559902080, 0 }, + {1569913600, 117815248 }, + {1596862336, 224162928 }, + {1640492800, 325650848 }, + {1702660352, 423060736 }, + {1785997696, 514412544 }, + {1896788608, 597466432 }, + {2042241920, 664027712 }, -const UWord8 sur_coherence_cb_masa[MASA_MAX_NO_CV_SUR_COH*MASA_NO_CB_SUR_COH] = -{ - 16, 99, 0, 0, 0, 0, 0, 0, - 12, 64, 167, 0, 0, 0, 0, 0, - 10, 45, 100, 218, 0, 0, 0, 0, - 8, 34, 70, 124, 235, 0, 0, 0, - 7, 27, 55, 90, 141, 242, 0, 0, - 7, 23, 45, 71, 105, 153, 247, 0, - 6, 20, 38, 60, 86, 119, 165, 249 -}; + /* column 9 (|ILD| = 19): */ + {1714196608, 0 }, + {1722634112, 90359672 }, + {1745223424, 171238192 }, + {1781415040, 247171072 }, + {1832190080, 318199104 }, + {1898830848, 382271424 }, + {1984989952, 437025792 }, + {2094086528, 475912448 }, -const Word16 idx_cb_sur_coh_masa[MASA_MAX_NO_CV_SUR_COH] = { 0, 1, 2, 3, 4, 5, 5, 6 }; + /* column 10 (|ILD| = 22): */ + {1831427712, 0 }, + {1838194432, 67828272 }, + {1856228992, 128123168 }, + {1884882944, 183977072 }, + {1924581248, 235132272 }, + {1975822336, 279821408 }, + {2040659200, 316058048 }, + {2120554240, 339023232 }, -const Word16 len_huf_masa[MASA_NO_CV_COH1] = { 4, 2, 1, 3, 4 }; + /* column 11 (|ILD| = 25): */ + {1918819584, 0 }, + {1924055168, 50102940 }, + {1937964416, 94399088 }, + {1959916032, 135003712 }, + {1990038784, 171579648 }, + {2028424960, 202728896 }, + {2076217216, 226931040 }, + {2133943808, 240762976 }, -const Word16 huff_code_av_masa[MASA_NO_CV_COH1] = { 15, 2, 0, 6, 14 }; + /* column 12 (|ILD| = 30): */ + {2015827840, 0 }, + {2019068416, 29502130 }, + {2027636864, 55420112 }, + {2041056512, 78889960 }, + {2059271424, 99626064 }, + {2082150784, 116769424 }, + {2110128128, 129415952 }, + {2143192960, 135682304 }, -const Word16 no_theta_masa[NO_SPHERICAL_GRIDS-2] = /* from 1 to 11 bits */ -{ /*1, 1,*/ 2 ,2 , 4, 5, 6, 7, 10, 14, 19 - /*0, 2, 8, 6, 7, 12, 14, 16*/ -}; + /* column 13 (|ILD| = 35): */ + {2072441984, 0 }, + {2074364032, 17033840 }, + {2079438464, 31939524 }, + {2087347712, 45337676 }, + {2098012032, 57039312 }, + {2111296384, 66537632 }, + {2127368192, 73321536 }, + {2146126464, 76351632 }, -const Word16 no_phi_masa[NO_SPHERICAL_GRIDS][MAX_NO_THETA] = /* from 1 to 11 bits*/ -{ - { 2 }, - { 4 }, - { 4, 2 }, - { 8, 4 }, /* 8, 4*/ - { 12, 7, 2, 1 }, /* 12, */ - { 14, 13, 9, 2, 1 }, - { 22, 21, 17, 11, 3, 1 }, - { 33, 32, 29, 23, 17, 9, 1 }, - { 48, 47, 45, 41, 35, 28, 20, 12, 2, 1 }, - { 60, 60, 58, 56, 54, 50, 46, 41, 36, 30, 23, 17, 10, 1 }, - { 89, 89, 88, 86, 84, 81, 77, 73, 68, 63, 57, 51, 44, 38, 30, 23, 15, 8, 1 } -}; + /* column 14 (|ILD| = 40): */ + {2104959232, 0 }, + {2106073728, 9723806 }, + {2109011456, 18212808 }, + {2113579136, 25810606 }, + {2119712384, 32401234 }, + {2127314432, 37692632 }, + {2136458496, 41399188 }, + {2147054208, 42945376 }, -const Word16 MASA_band_grouping_24[24 + 1] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30, 40, 60 -}; + /* column 15 (|ILD| = 45): */ + {2123466240, 0 }, + {2124103936, 5514738 }, + {2125783296, 10322954 }, + {2128390400, 14615774 }, + {2131882240, 18322330 }, + {2136200832, 21283710 }, + {2141376256, 23332410 }, + {2147348352, 24150602 }, -const Word16 MASA_band_mapping_24_to_18[18 + 1] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21, 22, 23, 24 + /* column 16 (|ILD| = 50): */ + {2133943808, 0 }, + {2134306688, 3115998 }, + {2135260160, 5830418 }, + {2136737664, 8250632 }, + {2138715520, 10335839 }, + {2141157120, 11995844 }, + {2144077696, 13136157 }, + {2147440640, 13580687 } }; -const Word16 MASA_band_mapping_24_to_12[12 + 1] = -{ - 0, 1, 2, 3, 4, 5, 7, 9, 12, 15, 20, 22, 24 -}; -const Word16 MASA_band_mapping_24_to_8[8 + 1] = +/* tables for adaptive Golomb-Rice coding of DFT stereo parameters */ +const Word16 dft_code_itd[] = { - 0, 1, 2, 3, 5, 8, 12, 20, 24 + 0, 3, 4, 13, 8, 9, 12, 5, 10, 44, 23, 60, 45, 31, 235, 59, 28, 61, 234, 116 }; -const Word16 MASA_band_mapping_24_to_5[5 + 1] = +const Word16 dft_len_itd[] = { - 0, 1, 3, 7, 15, 24 + 2, 3, 4, 4, 4, 4, 4, 4, 4, 6, 5, 6, 6, 5, 8, 6, 5, 6, 8, 7 }; -const Word16 MASA_grouping_8_to_5[8] = +const Word16 dft_maps_rpg[] = { - 0, 1, 1, 2, 3, 3, 4, 4 + 0, 1, 2, 3, 4, 5, 6, 7, + 2, 0, 1, 3, 4, 5, 6, 7, + 6, 2, 0, 1, 3, 4, 5, 7, + 7, 5, 2, 0, 1, 3, 4, 6, + 7, 6, 4, 3, 1, 0, 2, 5, + 7, 6, 5, 3, 2, 1, 0, 4, + 7, 6, 5, 4, 3, 2, 0, 1, + 7, 6, 5, 4, 3, 2, 0, 1, + 6, 5, 4, 3, 1, 0, 2, 7, }; -const Word16 MASA_grouping_12_to_5[12] = +const Word16 dft_maps_sg[NO_SYMB_GR_SIDE_G * NO_SYMB_GR_SIDE_G] = { - 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4 + 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, + 1, 0, 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, + 15, 4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 12, 9, 4, 1, 0, 2, 3, 5, 6, 7, 8, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 16, 14, 8, 4, 2, 0, 1, 3, 5, 6, 7, 9, 10, 11, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 18, 16, 14, 10, 5, 0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 15, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 21, 19, 17, 15, 8, 4, 2, 0, 1, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 21, 19, 17, 15, 12, 8, 4, 0, 1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 21, 19, 17, 15, 13, 11, 9, 3, 0, 1, 2, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 24, 22, 20, 18, 16, 14, 12, 9, 6, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 15, 17, 19, 21, 23, 25, 26, 27, 28, 29, 30, + 25, 23, 21, 19, 17, 15, 13, 11, 9, 6, 0, 1, 2, 3, 4, 5, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27, 28, 29, 30, + 27, 25, 23, 21, 19, 17, 15, 13, 11, 8, 5, 0, 1, 2, 3, 4, 6, 7, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 29, 30, + 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 0, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 28, 29, 30, + 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 30, + 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 0, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, + 30, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, + 30, 29, 28, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, + 30, 29, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 9, 7, 6, 4, 3, 2, 1, 0, 5, 8, 11, 13, 15, 17, 19, 21, 23, 25, 27, + 30, 29, 28, 27, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 7, 5, 4, 3, 2, 1, 0, 6, 9, 11, 13, 15, 17, 19, 21, 23, 25, + 30, 29, 28, 27, 26, 25, 23, 21, 19, 17, 15, 13, 11, 10, 8, 7, 5, 4, 3, 2, 1, 0, 6, 9, 12, 14, 16, 18, 20, 22, 24, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 18, 16, 14, 12, 10, 8, 7, 6, 5, 4, 2, 1, 0, 3, 9, 11, 13, 15, 17, 19, 21, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 18, 16, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0, 4, 8, 12, 15, 17, 19, 21, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 20, 18, 16, 14, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, 2, 4, 8, 15, 17, 19, 21, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 17, 15, 13, 12, 11, 9, 8, 7, 6, 4, 3, 2, 1, 0, 5, 10, 14, 16, 18, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 15, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, 2, 4, 8, 14, 16, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 11, 10, 8, 7, 6, 5, 3, 2, 0, 1, 4, 9, 12, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 3, 2, 1, 0, 4, 15, + 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, 0, 1, + 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 }; -const Word16 MASA_grouping_18_to_5[18] = -{ - 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 -}; -const Word16 MASA_grouping_24_to_5[24] = -{ - 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 -}; +/*------------------------------------------------------------------------- + * Range Coder ROM tables + *------------------------------------------------------------------------*/ -/* IVAS_13k2, IVAS_16k4, IVAS_24k4, IVAS_32k, IVAS_48k, IVAS_64k, IVAS_80k, IVAS_96k, IVAS_128k, IVAS_160k, IVAS_192k, IVAS_256k, IVAS_384k, IVAS_512k */ -const Word16 masa_bits[IVAS_NUM_ACTIVE_BRATES] = +/* Create separate tables for cumulative frequency and symbol frequency */ +const UWord16 cum_freq_ari_pk_s17_LC_ext[RANGE_N_CONTEXT][1 + RANGE_N_SYMBOLS] = { - 50, 60, 70, 85, 140, 180, 220, 256, 350, 432, 528, 832, 1024, MASA_MAX_BITS + { 0,16,47,153,241,269,325,468,591,674,798,912,1017,1082,1183,1277,1364,16384 }, + { 0,7401,7844,7886,7899,12065,12718,12790,12805,14099,14476,14533,14549,15058,15264,15299,15310,16384 }, + { 0,4362,6345,6864,7038,9037,11049,11736,12002,12569,13301,13656,13822,14021,14334,14515,14607,16384 }, + { 0,2955,5183,5822,6013,8153,10671,11614,11943,12586,13540,14025,14232,14437,14770,14978,15080,16384 }, + { 0,3155,4981,5615,5855,7969,9953,10739,11073,11936,12837,13208,13383,13767,14203,14400,14498,16384 }, + { 0,1216,2630,3264,3558,4831,6679,7661,8157,8709,9622,10204,10542,10799,11243,11568,11777,16384 }, + { 0,1759,3641,4350,4612,6325,8678,9732,10161,10790,11790,12361,12642,12883,13295,13566,13720,16384 }, + { 0,1109,2705,3433,3732,5226,7532,8732,9263,9978,11142,11842,12188,12490,12986,13321,13520,16384 }, + { 0,11524,13046,13170,13191,14956,15708,15813,15837,16028,16162,16195,16204,16245,16282,16295,16300,16384 }, + { 0,8027,10586,10909,10974,13291,14861,15157,15232,15535,15824,15914,15943,16014,16090,16123,16136,16384 }, + { 0,834,2034,2674,2997,4087,5843,6891,7455,8030,9013,9688,10085,10376,10893,11277,11528,16384 }, + { 0,6038,9086,9451,9519,12332,14521,14913,15003,15329,15711,15848,15893,15955,16045,16091,16111,16384 }, + { 0,4732,7685,8354,8545,10717,12924,13618,13852,14291,14842,15083,15181,15314,15491,15582,15625,16384 }, + { 0,745,1783,2347,2655,3537,4963,5864,6406,6863,7664,8248,8634,8891,9351,9708,9958,16384 }, + { 0,3957,6794,7669,7998,9743,11676,12498,12869,13313,13894,14186,14332,14498,14714,14835,14906,16384 }, + { 0,2779,5388,6021,6201,8582,11352,12260,12544,13117,13981,14408,14580,14751,15039,15213,15298,16384 }, + { 0,448,1160,1625,1920,2576,3706,4518,5053,5474,6234,6835,7262,7531,8032,8446,8758,16384 }, + { 0,1,2,1555,2246,2247,2248,3489,4112,5449,6596,7302,7710,8311,8876,9266,9517,16384 }, + { 0,2496,4910,5544,5722,8049,10799,11689,11973,12583,13467,13878,14047,14234,14537,14712,14803,16384 }, + { 0,921,2222,2880,3188,4407,6321,7406,7955,8573,9616,10296,10679,10978,11502,11880,12118,16384 }, + { 0,2620,4443,5017,5233,7072,9213,10083,10441,11049,11954,12442,12676,12918,13310,13565,13705,16384 }, + { 0,11205,13084,13178,13187,15164,16010,16081,16091,16213,16303,16321,16325,16340,16355,16360,16362,16384 }, + { 0,358,916,1288,1542,2055,2937,3594,4062,4399,5017,5524,5907,6136,6573,6941,7236,16384 }, + { 0,3575,5093,5536,5735,7408,9185,9878,10188,10727,11497,11933,12165,12410,12794,13019,13166,16384 }, + { 0,1,2,640,1036,1037,1038,1670,2096,2696,3287,3732,4056,4417,4800,5106,5339,16384 }, + { 0,969,1397,1518,1578,2633,3338,3566,3675,4197,4664,4857,4957,5288,5625,5783,5874,16384 }, + { 0,10458,12104,12294,12331,14246,15264,15437,15481,15752,15971,16031,16050,16120,16186,16210,16218,16384 }, + { 0,7178,9744,10039,10093,12701,14612,14961,15042,15360,15732,15869,15917,15978,16070,16117,16139,16384 }, + { 0,1298,2418,2879,3113,4146,5509,6227,6621,7053,7755,8229,8539,8776,9186,9492,9714,16384 }, + { 0,4957,7785,8252,8357,10978,13372,13955,14114,14561,15140,15378,15464,15570,15730,15820,15860,16384 }, + { 0,4823,8164,8570,8647,11604,14169,14653,14763,15105,15554,15727,15785,15852,15960,16018,16045,16384 }, + { 0,4735,7010,7517,7660,9986,12230,12914,13131,13666,14374,14689,14814,14972,15212,15342,15404,16384 }, + { 0,3363,5881,6658,6941,8864,11113,12015,12368,12889,13643,14019,14203,14394,14665,14823,14906,16384 }, + { 0,2569,4996,5779,6068,7917,10251,11209,11602,12129,12918,13321,13520,13696,13976,14155,14259,16384 }, + { 0,209,577,848,1046,1378,1982,2465,2835,3072,3513,3893,4202,4374,4703,4994,5241,16384 }, + { 0,2074,4337,5048,5274,7319,10003,11066,11446,12105,13112,13652,13885,14100,14464,14691,14810,16384 }, + { 0,1619,3560,4288,4550,6381,8955,10102,10543,11239,12362,12982,13261,13516,13958,14234,14381,16384 }, + { 0,89,257,441,582,734,1024,1325,1568,1716,1983,2222,2430,2545,2750,2941,3109,16384 }, + { 0,2202,3563,4044,4264,5686,7344,8100,8476,9006,9835,10331,10612,10864,11304,11599,11787,16384 }, + { 0,1220,2801,3492,3784,5223,7387,8496,8998,9640,10711,11369,11711,11993,12486,12829,13035,16384 }, + { 0,12626,13813,13903,13917,15396,15906,15972,15987,16139,16230,16251,16257,16289,16315,16323,16326,16384 }, + { 0,1579,3191,3831,4099,5678,7788,8761,9206,9842,10821,11388,11681,11958,12417,12722,12902,16384 }, + { 0,597,1514,2064,2379,3237,4679,5637,6213,6733,7649,8316,8755,9052,9599,10023,10323,16384 }, + { 0,9273,11762,12080,12151,14038,15210,15446,15514,15725,15929,15995,16019,16068,16124,16148,16158,16384 }, + { 0,9238,11681,11852,11872,14306,15644,15801,15828,16013,16183,16231,16243,16266,16297,16312,16318,16384 }, + { 0,6791,9200,9531,9594,12240,14178,14552,14639,15064,15506,15643,15687,15785,15908,15960,15983,16384 }, + { 0,7175,10415,10905,11033,13038,14621,15002,15123,15367,15651,15762,15806,15864,15938,15974,15992,16384 }, + { 0,5060,7703,8132,8225,10934,13270,13778,13911,14397,14972,15173,15242,15367,15537,15619,15654,16384 }, + { 0,3721,6311,6857,6992,9557,12180,12895,13098,13671,14418,14718,14830,14984,15212,15333,15390,16384 }, + { 0,5971,9288,10044,10269,11991,13680,14228,14437,14750,15130,15293,15374,15459,15579,15642,15677,16384 }, + { 0,3047,5311,5907,6078,8339,10850,11679,11946,12580,13442,13854,14024,14220,14534,14716,14810,16384 }, + { 0,2061,4280,4993,5228,7201,9735,10735,11097,11708,12606,13082,13295,13498,13836,14043,14161,16384 }, + { 0,4738,7949,8880,9234,10781,12502,13214,13531,13897,14355,14593,14718,14835,14998,15096,15153,16384 }, + { 0,3237,5045,5632,5860,7609,9702,10608,10986,11571,12476,12978,13230,13451,13830,14074,14208,16384 }, + { 0,1833,3889,4677,5028,6422,8379,9378,9884,10350,11086,11545,11809,12003,12327,12559,12711,16384 }, + { 0,3989,6858,7352,7459,10254,12936,13571,13735,14240,14895,15153,15242,15364,15548,15646,15690,16384 }, + { 0,1463,3197,3909,4220,5626,7609,8632,9127,9657,10520,11078,11380,11607,11991,12265,12442,16384 }, + { 0,14233,15083,15108,15110,16069,16300,16314,16316,16352,16370,16373,16374,16377,16380,16381,16382,16384 }, + { 0,1,2,2610,3293,3294,3295,5097,5671,8467,10332,11119,11437,12223,12850,13185,13345,16384 }, + { 0,2010,4053,4696,4910,6879,9391,10386,10750,11393,12376,12886,13119,13348,13726,13967,14099,16384 }, + { 0,7586,10517,10758,10791,13543,15346,15577,15619,15846,16082,16150,16169,16202,16245,16265,16273,16384 }, + { 0,3059,5772,6369,6524,9041,11801,12582,12813,13361,14115,14439,14567,14714,14944,15075,15141,16384 }, + { 0,8643,10594,10813,10856,13274,14686,14920,14975,15350,15680,15771,15799,15897,16003,16042,16057,16384 }, + { 0,6720,8878,9325,9467,11564,13248,13744,13929,14384,14880,15087,15167,15311,15488,15569,15607,16384 }, }; -const Word16 masa_bits_LR_stereo[4] = +const UWord16 sym_freq_ari_pk_s17_LC_ext[RANGE_N_CONTEXT][RANGE_N_SYMBOLS] = { - 50, 50, 60, 70 + { 16,31,106,88,28,56,143,123,83,124,114,105,65,101,94,87,15020 }, + { 7401,443,42,13,4166,653,72,15,1294,377,57,16,509,206,35,11,1074 }, + { 4362,1983,519,174,1999,2012,687,266,567,732,355,166,199,313,181,92,1777 }, + { 2955,2228,639,191,2140,2518,943,329,643,954,485,207,205,333,208,102,1304 }, + { 3155,1826,634,240,2114,1984,786,334,863,901,371,175,384,436,197,98,1886 }, + { 1216,1414,634,294,1273,1848,982,496,552,913,582,338,257,444,325,209,4607 }, + { 1759,1882,709,262,1713,2353,1054,429,629,1000,571,281,241,412,271,154,2664 }, + { 1109,1596,728,299,1494,2306,1200,531,715,1164,700,346,302,496,335,199,2864 }, + { 11524,1522,124,21,1765,752,105,24,191,134,33,9,41,37,13,5,84 }, + { 8027,2559,323,65,2317,1570,296,75,303,289,90,29,71,76,33,13,248 }, + { 834,1200,640,323,1090,1756,1048,564,575,983,675,397,291,517,384,251,4856 }, + { 6038,3048,365,68,2813,2189,392,90,326,382,137,45,62,90,46,20,273 }, + { 4732,2953,669,191,2172,2207,694,234,439,551,241,98,133,177,91,43,759 }, + { 745,1038,564,308,882,1426,901,542,457,801,584,386,257,460,357,250,6426 }, + { 3957,2837,875,329,1745,1933,822,371,444,581,292,146,166,216,121,71,1478 }, + { 2779,2609,633,180,2381,2770,908,284,573,864,427,172,171,288,174,85,1086 }, + { 448,712,465,295,656,1130,812,535,421,760,601,427,269,501,414,312,7626 }, + { 1,1,1553,691,1,1,1241,623,1337,1147,706,408,601,565,390,251,6867 }, + { 2496,2414,634,178,2327,2750,890,284,610,884,411,169,187,303,175,91,1581 }, + { 921,1301,658,308,1219,1914,1085,549,618,1043,680,383,299,524,378,238,4266 }, + { 2620,1823,574,216,1839,2141,870,358,608,905,488,234,242,392,255,140,2679 }, + { 11205,1879,94,9,1977,846,71,10,122,90,18,4,15,15,5,2,22 }, + { 358,558,372,254,513,882,657,468,337,618,507,383,229,437,368,295,9148 }, + { 3575,1518,443,199,1673,1777,693,310,539,770,436,232,245,384,225,147,3218 }, + { 1,1,638,396,1,1,632,426,600,591,445,324,361,383,306,233,11045 }, + { 969,428,121,60,1055,705,228,109,522,467,193,100,331,337,158,91,10510 }, + { 10458,1646,190,37,1915,1018,173,44,271,219,60,19,70,66,24,8,166 }, + { 7178,2566,295,54,2608,1911,349,81,318,372,137,48,61,92,47,22,245 }, + { 1298,1120,461,234,1033,1363,718,394,432,702,474,310,237,410,306,222,6670 }, + { 4957,2828,467,105,2621,2394,583,159,447,579,238,86,106,160,90,40,524 }, + { 4823,3341,406,77,2957,2565,484,110,342,449,173,58,67,108,58,27,339 }, + { 4735,2275,507,143,2326,2244,684,217,535,708,315,125,158,240,130,62,980 }, + { 3363,2518,777,283,1923,2249,902,353,521,754,376,184,191,271,158,83,1478 }, + { 2569,2427,783,289,1849,2334,958,393,527,789,403,199,176,280,179,104,2125 }, + { 209,368,271,198,332,604,483,370,237,441,380,309,172,329,291,247,11143 }, + { 2074,2263,711,226,2045,2684,1063,380,659,1007,540,233,215,364,227,119,1574 }, + { 1619,1941,728,262,1831,2574,1147,441,696,1123,620,279,255,442,276,147,2003 }, + { 89,168,184,141,152,290,301,243,148,267,239,208,115,205,191,168,13275 }, + { 2202,1361,481,220,1422,1658,756,376,530,829,496,281,252,440,295,188,4597 }, + { 1220,1581,691,292,1439,2164,1109,502,642,1071,658,342,282,493,343,206,3349 }, + { 12626,1187,90,14,1479,510,66,15,152,91,21,6,32,26,8,3,58 }, + { 1579,1612,640,268,1579,2110,973,445,636,979,567,293,277,459,305,180,3482 }, + { 597,917,550,315,858,1442,958,576,520,916,667,439,297,547,424,300,6061 }, + { 9273,2489,318,71,1887,1172,236,68,211,204,66,24,49,56,24,10,226 }, + { 9238,2443,171,20,2434,1338,157,27,185,170,48,12,23,31,15,6,66 }, + { 6791,2409,331,63,2646,1938,374,87,425,442,137,44,98,123,52,23,401 }, + { 7175,3240,490,128,2005,1583,381,121,244,284,111,44,58,74,36,18,392 }, + { 5060,2643,429,93,2709,2336,508,133,486,575,201,69,125,170,82,35,730 }, + { 3721,2590,546,135,2565,2623,715,203,573,747,300,112,154,228,121,57,994 }, + { 5971,3317,756,225,1722,1689,548,209,313,380,163,81,85,120,63,35,707 }, + { 3047,2264,596,171,2261,2511,829,267,634,862,412,170,196,314,182,94,1574 }, + { 2061,2219,713,235,1973,2534,1000,362,611,898,476,213,203,338,207,118,2223 }, + { 4738,3211,931,354,1547,1721,712,317,366,458,238,125,117,163,98,57,1231 }, + { 3237,1808,587,228,1749,2093,906,378,585,905,502,252,221,379,244,134,2176 }, + { 1833,2056,788,351,1394,1957,999,506,466,736,459,264,194,324,232,152,3673 }, + { 3989,2869,494,107,2795,2682,635,164,505,655,258,89,122,184,98,44,694 }, + { 1463,1734,712,311,1406,1983,1023,495,530,863,558,302,227,384,274,177,3942 }, + { 14233,850,25,2,959,231,14,2,36,18,3,1,3,3,1,1,2 }, + { 1,1,2608,683,1,1,1802,574,2796,1865,787,318,786,627,335,160,3039 }, + { 2010,2043,643,214,1969,2512,995,364,643,983,510,233,229,378,241,132,2285 }, + { 7586,2931,241,33,2752,1803,231,42,227,236,68,19,33,43,20,8,111 }, + { 3059,2713,597,155,2517,2760,781,231,548,754,324,128,147,230,131,66,1243 }, + { 8643,1951,219,43,2418,1412,234,55,375,330,91,28,98,106,39,15,327 }, + { 6720,2158,447,142,2097,1684,496,185,455,496,207,80,144,177,81,38,777 }, }; -const Word16 mcmasa_bits[IVAS_NUM_ACTIVE_BRATES] = -{ - 50, 70, 80, 120, 140, 160, 220, 256, 288, 432, 528, 832, 1024, MASA_MAX_BITS -}; -const UWord8 masa_nbands[IVAS_NUM_ACTIVE_BRATES] = -{ - 5, 5, 5, 5, 5, 5, 5, 5, 8, 12, 18, 24, 24, 24 -}; +/*------------------------------------------------------------------------- + * ECLVQ Stereo ROM tables + *------------------------------------------------------------------------*/ -const UWord8 masa_joined_nbands[IVAS_NUM_ACTIVE_BRATES] = +/* table with round(ECSQ_PROB_TOTAL / index) for entropy coding, with i in {1, .., ECSQ_SEGMENT_SIZE} */ +const UWord16 ECSQ_tab_inverse[1 + ECSQ_SEGMENT_SIZE] = { - 5, 5, 5, 8, 12, 12, 12, 18, 18, 18, 18, 24, 24, 24 + 0, 16384, 8192, 5461, 4096, 3277, 2731, 2341, 2048 }; -const UWord8 masa_twodir_bands[IVAS_NUM_ACTIVE_BRATES] = -{ - 0, 0, 0, 0, 0, 1, 1, 1, 3, 4, 6, 6, 9, 24 -}; -const UWord8 masa_twodir_bands_joined[IVAS_NUM_ACTIVE_BRATES] = +const Word16 tdm_bit_allc_tbl[5][6] = { - 0, 0, 0, 0, 0, 2, 2, 3, 4, 6, 8, 9, 12, MASA_MAXIMUM_TWO_DIR_BANDS + /* IC -- UC -- GC -- TM --AC */ + { 1650, 3500, 0, 4400, 0, 5000 }, /* IVAS_13k2 */ + { 1650, 3500, 0, 5000, 0, 5000 }, /* IVAS_16k4 */ + { 1650, 3500, 0, 6000, 0, 5000 }, /* IVAS_24k4 */ + { 1650, 6050, 0, 10000, 0, 10000 }, /* IVAS_32k */ + { 1650, 6050, 0, 13000, 0, 14000 } /* IVAS_48k */ }; -/*----------------------------------------------------------------------------------* - * OMASA ROM tables - *----------------------------------------------------------------------------------*/ - -const Word32 sep_object_brate[][MAX_NUM_OBJECTS] = -{ - {0, 0, 0, 0}, /* 13k2 */ - {0, 0, 0, 0}, /* 16k4 */ - {9600, 0, 0, 0}, /* 24k4 */ - {IVAS_13k2, 0, 0, 0}, /* 32k */ - {16000, 11000, 0, 0}, /* 48k */ - {16000, 11700, 0, 0}, /* 64k */ - {20000, 16000, 0, 0}, /* 80k */ - {IVAS_32k, 20000, 20000, 0}, /* 96k */ - {IVAS_32k, IVAS_24k4, 24000, 24000}, /* 128k */ - {IVAS_48k, IVAS_32k, IVAS_24k4, 24000}, /* 160k */ - {IVAS_64k, IVAS_48k, IVAS_32k, IVAS_24k4}, /* 192k */ - {IVAS_96k, IVAS_64k, IVAS_48k, IVAS_32k}, /* 256k */ - {IVAS_128k, IVAS_80k, IVAS_64k, IVAS_48k}, /* 384k */ - {IVAS_128k, IVAS_96k, IVAS_80k, IVAS_64k} /* 512k */ -}; +const Word16 fast_FCB_bits_2sfr[] = {8, 14, 18, 20, 24, 128/*stop value*/}; -/* column wise DCT matrices for 4 5, and 8 dim */ -/*----------------------------------------------------------------------------------* - * Param ISM ROM tables - *----------------------------------------------------------------------------------*/ +const Word16 fast_FCB_rates_2sfr[] = {/*16*50,*/ (8+14)*50, 28*50, 32*50, 34*50, 36*50, 38*50, 40*50, 42*50, 44*50, 48*50}; -const Word16 Param_ISM_band_grouping[MAX_PARAM_ISM_NBANDS + 1] = -{ - 0, 1, 2, 3, 4, 6, 8, 11, 15, 21, 31, 60 -}; /*----------------------------------------------------------------------------------* - * LFE coding ROM tables + * MDCT Stereo ROM tables *----------------------------------------------------------------------------------*/ -const ivas_lfe_freq_models ivas_str_lfe_freq_models = -{ - { 16384, 14924, 13463, 12003, 10542, 9082, 7622, 6161, - 4701, 4336, 3970, 3605, 3240, 2875, 2510, 2145, - 1780, 1689, 1597, 1506, 1415, 1323, 1232, 1141, - 1050, 1004, 958, 913, 867, 821, 776, 730, - 685, 639, 593, 548, 502, 456, 411, 365, - 319, 297, 274, 251, 228, 205, 183, 160, - 137, 126, 114, 103, 91, 80, 68, 57, - 46, 40, 34, 29, 23, 17, 11, 6, 0 }, - - { 16384, 13463, 10542, 7622, 4701, 3970, 3240, 2510, - 1780, 1597, 1415, 1232, 1050, 958, 867, 776, - 685, 593, 502, 411, 319, 274, 228, 183, - 137, 114, 91, 68, 46, 34, 23, 11, 0 }, - - { 16384, 4701, 1780, 1050, 685, 319, 137, 46, - 0, }, - - { 16384, 3277, 0 }, - - { 16384, 13463, 10542, 7622, 4701, 3970, 3240, 2510, - 1780, 1597, 1415, 1232, 1050, 958, 867, 776, - 685, 593, 502, 411, 319, 274, 228, 183, - 137, 114, 91, 68, 46, 34, 23, 11, - 0 }, - - { 16384, 10542, 4701, 3240, 1780, 1415, 1050, 867, - 685, 502, 319, 228, 137, 91, 46, 23, - 0 }, - - { 16384, 4468, 1489, 745, 0 }, 0, -}; - -const Word16 ivas_lfe_num_ele_in_coder_models[2][4] = -{ - { 63, 31, 7, 1 },{ 31, 15, 3, 0 } -}; - -const Word16 ivas_lfe_log2_num_ele_in_coder_models_fx[2][4] = -{ - { 6, 5, 3, 1 },{ 5, 4, 2, 0 } -}; + /* PsychLPC */ -const Word16 ivas_lfe_num_dct_pass_bins_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 8, 6 }; +const SpectrumWarping sw32000Hz[] = +{{ + { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, + 6, 8, 8, 8, 8, 8, 10, 10, 10, 10, 12, 12, 12, 12, 14, 14, + 14, 16, 18, 18, 18, 20, 22, 22, 22, 24, 26, 26, 26, 28, 30, 32 + }, + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, + 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10 + }, +}}; -const Word16 ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 1, 0 }; +const SpectrumWarping sw25600Hz[] = +{{ + { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, + 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 10, 12, 12, 12, 12, + 12, 12, 14, 14, 14, 14, 14, 16, 16, 18, 18, 18, 18, 18, 20, 20 + }, + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 + }, +}}; -const Word16 ivas_lfe_lpf_delay_Q15[2] = { 57, 114 }; +const SpectrumWarping sw16000Hz[] = +{{ + { + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 + }, + { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 + }, +}}; -const Word16 dirac_gains_P_idx[16] = -{ - -1, 1, 0, 1, 4, 3, 2, 3, 4, 8, 7, 6, 5, 6, 7, 8 -}; +const MDCTStereoBands_config mdctStereoBands_32000_640[] = +{{ + /*TCX 20*/ + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 20, 20, 20, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 42, + 64, 64, 96, 160}, + {44, 41,38, 29},/*number of bands for frame lengths 960, 640, 512, 320 respectively*/ -/*----------------------------------------------------------------------------------* - * FB ROM tables - *----------------------------------------------------------------------------------*/ + /*TCX 10*/ + { + 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 20, 32, 32, + 32, 48, 80 + }, + {33, 29, 26, 18}/*number of bands for frame lengths 480, 320, 256, 160 respectively*/ +}}; -const Word32 ivas_fb_fcs_12band_1ms_fx[IVAS_FB_BANDS_12] = -{ - 17895696, 53687092, 89478488, 125269880, - 161061280, 196852672, 232644064, 304226848, - 465288128, 715827904, 1091637520, 1735882615 -};/*Q31*/ -const Word16 ivas_fb_abs_bins_per_band_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = -{ - { 24, 30, 30, 30, 30, 30, 42, 76, 124, 182, 291, 367 }, - { 24, 30, 30, 30, 30, 30, 42, 76, 124, 182, 260, 47 }, - { 24, 30, 30, 30, 30, 30, 42, 75, 122, 73, 0, 0 } -}; +const Word16 dft_cng_coh_u2i[9] = { 4, 5, 3, 6, 2, 7, 1, 8, 0 }; /* Coherence unary codeword -> residual codeword conversion table */ -const Word16 ivas_fb_abs_bins_start_offset_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = -{ - {0, 9, 25, 41, 57, 73, 88, 110, 158, 246, 380, 593 }, - {0, 9, 25, 41, 57, 73, 88, 110, 158, 246, 380, 593 }, - {0, 9, 25, 41, 57, 73, 88, 110, 159, 247, 0, 0 } -}; +const Word16 dft_cng_coh_i2u[9] = { 8, 6, 4, 2, 0, 1, 3, 5, 7 }; /* Coherence residual codeword -> unary codeword conversion table */ -const Word16 ivas_fb_bins_per_band_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = -{ - { - IVAS_FB_12_1MS_48K_END_BINS_BAND_0 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_0, - IVAS_FB_12_1MS_48K_END_BINS_BAND_1 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_1, - IVAS_FB_12_1MS_48K_END_BINS_BAND_2 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_2, - IVAS_FB_12_1MS_48K_END_BINS_BAND_3 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_3, - IVAS_FB_12_1MS_48K_END_BINS_BAND_4 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_4, - IVAS_FB_12_1MS_48K_END_BINS_BAND_5 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_5, - IVAS_FB_12_1MS_48K_END_BINS_BAND_6 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_6, - IVAS_FB_12_1MS_48K_END_BINS_BAND_7 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_7, - IVAS_FB_12_1MS_48K_END_BINS_BAND_8 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_8, - IVAS_FB_12_1MS_48K_END_BINS_BAND_9 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_9, - IVAS_FB_12_1MS_48K_END_BINS_BAND_10 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_10, - IVAS_FB_12_1MS_48K_END_BINS_BAND_11 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_11 - }, - { - IVAS_FB_12_1MS_32K_END_BINS_BAND_0 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_0, - IVAS_FB_12_1MS_32K_END_BINS_BAND_1 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_1, - IVAS_FB_12_1MS_32K_END_BINS_BAND_2 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_2, - IVAS_FB_12_1MS_32K_END_BINS_BAND_3 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_3, - IVAS_FB_12_1MS_32K_END_BINS_BAND_4 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_4, - IVAS_FB_12_1MS_32K_END_BINS_BAND_5 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_5, - IVAS_FB_12_1MS_32K_END_BINS_BAND_6 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_6, - IVAS_FB_12_1MS_32K_END_BINS_BAND_7 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_7, - IVAS_FB_12_1MS_32K_END_BINS_BAND_8 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_8, - IVAS_FB_12_1MS_32K_END_BINS_BAND_9 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_9, - IVAS_FB_12_1MS_32K_END_BINS_BAND_10 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_10, - IVAS_FB_12_1MS_32K_END_BINS_BAND_11 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_11 - }, - { - IVAS_FB_12_1MS_16K_END_BINS_BAND_0 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_0, - IVAS_FB_12_1MS_16K_END_BINS_BAND_1 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_1, - IVAS_FB_12_1MS_16K_END_BINS_BAND_2 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_2, - IVAS_FB_12_1MS_16K_END_BINS_BAND_3 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_3, - IVAS_FB_12_1MS_16K_END_BINS_BAND_4 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_4, - IVAS_FB_12_1MS_16K_END_BINS_BAND_5 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_5, - IVAS_FB_12_1MS_16K_END_BINS_BAND_6 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_6, - IVAS_FB_12_1MS_16K_END_BINS_BAND_7 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_7, - IVAS_FB_12_1MS_16K_END_BINS_BAND_8 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_8, - IVAS_FB_12_1MS_16K_END_BINS_BAND_9 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_9, - IVAS_FB_12_1MS_16K_END_BINS_BAND_10 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_10, - IVAS_FB_12_1MS_16K_END_BINS_BAND_11 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_11 - }, +const Word16 dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1] = { 15, 16, 17, 18 }; + + +const Word16 DirAC_band_grouping_12[12 + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 11, 17, 25, 40, 60 }; -const Word16 ivas_fb_bins_start_offset_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = + +const Word16 DirAC_band_grouping_6[6 + 1] = { - { - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_0, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_1, - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_2, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_3, - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_4, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_5, - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_6, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_7, - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_8, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_9, - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_10, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_11 - }, - { - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_0, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_1, - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_2, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_3, - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_4, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_5, - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_6, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_7, - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_8, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_9, - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_10, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_11 - }, - { - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_0, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_1, - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_2, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_3, - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_4, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_5, - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_6, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_7, - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_8, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_9, - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_10, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_11 - }, + 0, 1, 4, 8, 20, 30, 60 }; +const Word16 DirAC_band_grouping_5[5 + 1] = +{ + 0, 1, 3, 7, 15, 60 +}; -const Word16 ivas_num_active_bands[FB - WB + 1] = +const Word16 DirAC_block_grouping[MAX_PARAM_SPATIAL_SUBFRAMES + 1] = { - IVAS_16K_12BANDS_ACTIVE_BANDS, IVAS_FB_BANDS_12, IVAS_FB_BANDS_12 + 0, 4, 8, 12, 16 }; -/*------------------------------------------------------------------------------------------* - * SNS MSVQ codebooks and means - *------------------------------------------------------------------------------------------*/ +const Word16 DirAC_block_grouping_5ms_MDFT[MAX_PARAM_SPATIAL_SUBFRAMES + 1] = +{ + 0, 1, 2, 3, 4 +}; -const Word16 ivas_sns_cdbks_tcx20_levels[SNS_MSVQ_NSTAGES_TCX20] = { 128, 64, 32, 32 }; +const Word32 c_weights_fx[DIRAC_NO_FB_BANDS_MAX] /* Q30 */ = { 106970960, 1033798336, 1065867776, 1071704704, 1073381888, 1073741824, 1073494016, 1072883072, 1072012032, 1070930560, 1069665600, 1068232640, 1066641792, 1064899968, 1063012224, 1060982464, 1058814144, 1056510016, 1054072832, 1051505280, 1048809664, 1045988480, 1043044160, 1039979072, 1036795776, 1033496576, 1030084096, 1026560960, 1022929600, 1019192512, 1015352576, 1011412416, 1007374720, 1003242112, 999017472, 994703488, 990302976, 985818688, 981253568, 976610304, 971891712, 967100672, 962240064, 957312576, 952321088, 947268224, 942156992, 936990080, 931770048, 926499840, 921182016, 915819200, 910414208, 904969344, 899487488, 893970944, 888422272, 882843840, 877238144, 871607552, 865954432, 860280896, 854589184, 848881728, 843160384, 837427328, 831684672, 825934208, 820178240, 814418240, 808656320, 802894208, 797133568, 791376192, 785623744, 779877568, 774139520, 768410880, 762693184, 756987904, 751296064, 745619328, 739958784, 734315584, 728691008, 723086208, 717502016, 711939712, 706400064, 700884096, 695392768, 689926912, 684487232, 679074688, 673689856, 668333504, 663006464, 657709056, 652442176, 647206144, 642001600, 636828992, 631688896, 626581696, 621507776, 616467520, 611461184, 606489344, 601552064, 596649792, 591782528, 586950784, 582154560, 577394112, 572669696, 567981312, 563329088, 558713152, 554133568, 549590464, 545083840, 540613760, 536180160, 531783104, 527422528, 523098464, 518810784, 514559520, 510344672, 506165856, 502023360, 497916832, 493846304, 489811488, 485812448, 481848832, 477920672, 474027808, 470169952, 466347008, 462558848, 458805152, 455085920, 451400736, 447749600, 444132160, 440548320, 436997792, 433480416, 429995904, 426544032, 423124608, 419737376, 416382144, 413058720, 409766720, 406505984, 403276288, 400077280, 396908768, 393770656, 390662496, 387584064, 384535200, 381515616, 378525024, 375563200, 372629952, 369724864, 366847872, 363998592, 361176672, 358382176, 355614592, 352873760, 350159456, 347471328, 344809216, 342172864, 339562048, 336976384, 334415808, 331879840, 329368576, 326881472, 324418432, 321979104, 319563392, 317170976, 314801664, 312455232, 310131328, 307829856, 305550528, 303293088, 301057440, 298843168, 296650176, 294478304, 292327168, 290196672, 288086432, 285996512, 283926432, 281876224, 279845472, 277834016, 275841792, 273868480, 271913856, 269977792, 268059968, 266160304, 264278672, 262414768, 260568368, 258739360, 256927520, 255132768, 253354752, 251593392, 249848448, 248119936, 246407424, 244710816, 243030080, 241364928, 239715120, 238080672, 236461248, 234856752, 233267088, 231692016, 230131440, 228585136, 227053024, 225534848, 224030544, 222539872, 221062832 }; -const Word16 ivas_sns_cdbks_tcx20_bits[SNS_MSVQ_NSTAGES_TCX20] = { 7, 6, 5, 5 }; +/*----------------------------------------------------------------------* +* SPAR ROM tables +*-----------------------------------------------------------------------*/ -/* pre-rounded codebook vectors for singed Q4.12 represantation */ +const ivas_spar_br_table_t ivas_spar_br_table_consts[IVAS_SPAR_BR_TABLE_LEN] = +{ +/* When AGC is ON additional (AGC_BITS_PER_CH+1) bits may be taken from each core-coder channel + so minimum core-coder bitrate per channel can be min core-coder bitrates as per the table - AGC_BITS_PER_CH */ + { 13200, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 10000, 8150, 13150 } }, + { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, -const Word16 ivas_sns_cdbks_tcx10_levels[SNS_MSVQ_NSTAGES_TCX10] = { 128, 32, 8 }; + { 16400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 13200, 11350, 16350 } }, + { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, -const Word16 ivas_sns_cdbks_tcx10_bits[SNS_MSVQ_NSTAGES_TCX10] = { 7, 5, 3 }; + { 24400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 16400, 14850, 24350 } }, + { { 15, 1, 5, 1 },{ 15, 1, 3, 1 },{ 7, 1, 3, 1 } }, 0, 0, 0 }, + { 32000, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 24000, 20450, 31950 } }, + { { 21, 1, 5, 1 },{ 15, 1, 5, 1 },{ 15, 1, 3, 1 } }, 0, 0, 0 }, -const Word16 ivas_sns_cdbks_side_tcx20_levels[SNS_MSVQ_NSTAGES_SIDE] = { 32, 32 }; -const Word16 ivas_sns_cdbks_side_tcx20_bits[SNS_MSVQ_NSTAGES_SIDE] = { 5, 5 }; -const Word16 ivas_sns_cdbks_side_tcx10_levels[SNS_MSVQ_NSTAGES_SIDE] = { 32, 8 }; -const Word16 ivas_sns_cdbks_side_tcx10_bits[SNS_MSVQ_NSTAGES_SIDE] = { 5, 3 }; + { 48000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 24000, 21000, 31950 },{ 16000, 15000, 20400 } }, + { { 15, 7, 5, 1 },{ 15, 7, 3, 1 },{ 7, 7, 3, 1 } }, 1, 0, 0 }, + { 64000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 38000, 34050, 56000 },{ 16000, 15600, 20400 } },{ { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 1, 0 }, -const Word16 sns_1st_cdbk[2][2][8 * 32] = -{ - { /* split 1 */ - { /* TCX 20 */ - -10900, -11064, -10637, -10471, -9051, -6381, -4688, -2438, - -2119, -5087, -6702, -8118, -7586, -6343, -4828, -3406, - 2004, -3443, -4289, -3757, -3234, -2952, -2313, -1781, - 1749, 5598, 3916, 732, -1472, -2964, -3275, -2332, - -11978, -14369, -5600, -545, 981, -929, -57, 1903, - 1745, 391, 202, 115, 256, -291, -862, -1637, - -4052, 2059, 4709, 6768, 5595, 1975, -1723, -1218, - 2093, 7263, 8679, 7576, 3701, -2438, -4389, -2686, - -7120, -6279, -5715, -5520, -4752, -3125, -1856, -438, - 8131, -2543, -6285, -6723, -5588, -4321, -3264, -2164, - -653, -1301, -660, 608, 1598, 1805, 1698, 760, - 4882, 9309, 6333, 1734, 284, 364, 560, 1015, - -7686, -5737, -3443, -1642, 245, 1531, 1827, 1769, - -1468, 3782, 144, -5130, -6883, -5165, -1497, 2072, - -12937, -8429, -2619, 2894, 5004, 4710, 4627, 3740, - 3198, 3928, 4358, 4554, 3887, 2844, 1299, 129, - -13828, -12296, -9364, -7918, -5571, -1909, 307, 2047, - -4314, -1211, -559, -1061, -1928, -2228, -2359, -1902, - -309, -3224, -3404, -1895, -743, -59, 757, 908, - 10914, 5865, 1599, -386, -1392, -2285, -2236, -2042, - -11825, -16241, -11402, -3627, 6556, 8953, 6421, 1546, - 6102, 777, -301, 536, 902, 541, 210, -429, - -3052, 3997, 5389, 1842, -344, 1556, 2667, 2428, - 11788, 10894, 7448, 5423, 2372, -677, -2385, -3839, - -45, -7602, -8923, -7179, -3273, 65, 4500, 6726, - 5895, 626, -1610, -2598, -3240, -3540, -2930, -2156, - -971, 461, 1494, 4907, 5859, 5199, 3678, 2502, - 10766, 5297, 1844, 1236, 2498, 3503, 2846, 838, - -7816, -1212, 891, 2387, 1317, 2225, 1859, 1602, - 2376, 5357, 2088, -2719, -3419, -420, 2431, 2943, - -8383, -795, 4351, 7026, 7460, 7191, 5262, 3796, - 1522, 6283, 8714, 8222, 7434, 5768, 3586, 1499, - }, - { /* TCX 10 */ - -15596, -16321, -10264, -1002, 5955, 5543, -29, -1688, - 17, -3794, -6207, -7356, -6998, -6081, -4453, -2448, - -12543, -11530, -10186, -8817, -7083, -4440, -1946, 892, - 5198, 2751, -274, -2574, -4561, -6087, -5944, -4600, - -683, -2640, -2753, -1195, -239, -217, -286, 90, - -1400, -1146, -1853, -2845, -3456, -3788, -3171, -1969, - -1835, 392, 1725, 1209, -392, -1640, -2001, -1608, - 5770, 7707, 5210, 2112, -382, -2088, -2634, -3007, - -10766, -8101, -5137, -3754, -1881, 331, 2339, 3679, - -2637, -4640, -5811, -5651, -3790, -1359, 913, 1893, - -7793, -4768, -1762, -545, -717, -837, -441, -75, - 4030, 1770, 467, 379, 10, -1330, -2398, -2290, - -9395, -6952, -2494, 2022, 4753, 5614, 4443, 2642, - -1486, 1748, 859, -2586, -3368, -638, 2761, 3269, - -2408, 306, 3633, 6567, 5950, 2474, -621, -1421, - 5478, 7986, 9498, 8165, 5477, 1244, -523, -1586, - -13564, -14673, -10597, -5504, 1575, 8248, 7662, 4025, - 4978, -682, -3586, -4305, -3703, -3001, -2227, -1278, - -8002, -6831, -5558, -4868, -4243, -3393, -2486, -1110, - 11485, 5472, 1645, -533, -1792, -2814, -3169, -2706, - 1617, 421, 232, 1382, 2162, 2017, 1318, 744, - 3677, 5212, 1990, -1514, -2894, -2441, -451, 592, - 731, 4295, 5860, 3756, 1991, 1437, 869, 127, - 12736, 11722, 7768, 4682, 1574, -744, -1989, -3131, - -3490, -4269, -3681, -1531, 1111, 3327, 4138, 3815, - 7344, 1400, -1302, -1502, -1015, 57, 1212, 1498, - -4836, -1881, 1071, 2055, 2114, 2465, 2093, 1458, - 8569, 5879, 3654, 2879, 2530, 1703, 781, -233, - -3709, -990, 2338, 6227, 7083, 7102, 5657, 3401, - 3389, 6392, 5267, 1011, 275, 3519, 5236, 4339, - 599, 3752, 6943, 9211, 8152, 5568, 3337, 1838, - 9885, 9591, 7905, 8068, 7929, 7421, 4234, 757, - } - }, - { /* split 2 */ - { /* TCX 20 */ - -178, -3476, -5982, -7081, -7548, -7440, -6859, -5798, - -3596, -3670, -1501, 770, 812, -286, -2001, -3377, - -3998, -5191, -4988, -4421, -3889, -3571, -2738, -1969, - -2981, -2687, -1501, -83, 1136, 2377, 3248, 4105, - 1842, -41, -1972, -4282, -6779, -8405, -8674, -7835, - -259, 571, 2124, 3344, 2959, 1407, -750, -2523, - -524, -1956, -2855, -3202, -3939, -4666, -4907, -4782, - -5110, -4768, -3017, -663, 4188, 9210, 16602, 21081, - 4373, 4846, -603, -6495, -7289, -5540, -4749, -5527, - -1448, -1043, -619, -105, 356, 362, 542, 857, - 1373, -752, -5334, -6244, -3001, -932, -1040, -3125, - -2403, -1397, 612, 2449, 3920, 5231, 6819, 8581, - 2183, 1211, -111, -1084, -2836, -4977, -6701, -7284, - -751, 1255, 3408, 6474, 7503, 7026, 5413, 4464, - 935, 850, 589, 353, 160, -434, -939, -931, - 268, 2284, 3884, 5423, 6680, 7996, 9244, 9472, - 1075, 113, -1289, -4457, -7512, -5930, -1799, -571, - -3689, -4254, -3755, -2995, -1581, -135, 1049, 1589, - -1166, -1752, -1790, -1897, -1927, -1831, -1359, -805, - -1494, -735, 635, 1993, 2909, 3546, 4226, 4956, - 4435, 4299, 4269, 1328, -3731, -7621, -9319, -9170, - 1358, 2227, 3873, 4469, 4692, 4057, 2601, 1608, - 813, 398, -499, -666, -1286, -2271, -3316, -4025, - -3300, -1255, 2181, 6431, 10002, 12760, 13549, 12584, - 3714, 4180, 484, -2905, -2864, -1359, -1256, -2477, - 308, 868, 1373, 1629, 1793, 1834, 1814, 1746, - 1472, 798, -282, -1935, -1818, 320, 2221, 2914, - 2281, 3240, 2988, 1400, 2383, 4072, 5667, 6675, - 2672, 2678, 2874, 2096, -226, -2301, -3861, -4534, - 4988, 7231, 7641, 7731, 7061, 6447, 5411, 3513, - 3978, 4156, 4126, 2896, 1469, 759, 368, -68, - -264, 4210, 8534, 11008, 11606, 11888, 11072, 8949, - }, - { /* TCX 10 */ - -2852, -6158, -7231, -7830, -8012, -7922, -7556, -6706, - -3911, -5340, -5053, -4741, -4805, -4484, -3727, -3037, - -966, -1461, -1694, -2427, -3081, -3037, -2547, -2230, - -3455, -3315, -2451, -836, 1383, 3196, 3720, 3379, - 3052, 281, -3351, -6866, -9051, -9586, -8983, -8236, - -748, -4465, -4314, -2251, 29, -40, -3963, -6195, - 200, 1293, 2535, 2803, 1603, -186, -1397, -1697, - -1707, -265, 2196, 5295, 5894, 4216, 3440, 3826, - -237, -2133, -2279, -3149, -4377, -5638, -6520, -6764, - -2407, -2049, -1246, -664, -521, -430, -349, -211, - 3874, 1335, -1501, -2055, -1268, -990, -1852, -2871, - -1883, -1845, -1681, -484, 384, 2035, 5839, 9597, - 275, 380, 1048, 424, -1146, -3012, -4431, -5104, - -1699, -484, 756, 1261, 1279, 1377, 1975, 2590, - 2139, 4502, 3645, 4975, 6491, 5972, 5012, 4346, - -3821, -2581, -433, 2667, 6436, 10038, 11311, 8783, - 2359, -2689, -6604, -7039, -5992, -4268, -3711, -4840, - -2776, -4251, -4539, -3672, -2494, -1055, 280, 695, - 491, 866, 822, -44, -1009, -1165, -831, -538, - -1024, 91, 786, 1295, 2433, 3910, 4975, 5403, - 3117, 2590, 2337, -667, -4580, -8147, -9400, -9523, - -103, -630, -831, 669, 3062, 3398, 549, -1690, - 2113, 3467, 4279, 5047, 5344, 3361, 127, -2313, - -1199, 1153, 2914, 3688, 4260, 5421, 7471, 8831, - 2815, 2184, 316, -3058, -5596, -5564, -4343, -3793, - 922, 126, -1414, -1731, -1007, 359, 2029, 3088, - 4889, 4619, 2537, 1114, 950, 946, 799, 419, - -4271, -3750, -3359, -484, 1448, 4106, 10487, 20479, - 3818, 4687, 4064, 2212, -172, -2287, -3535, -4041, - 884, 2456, 3394, 2925, 2182, 2323, 2583, 2507, - 4767, 8057, 8263, 6461, 5003, 4055, 2923, 1845, - 19, 3813, 6926, 8432, 10141, 10850, 9692, 8383, - } - } -}; + { 80000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 46000, 43000, 56000 },{ 24000, 23000, 31950 } }, + { { 21, 7, 5, 1 },{ 15, 7, 5, 1 },{ 15, 7, 3, 1 } }, 1, 0, 0 }, + + { 96000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 47000, 42600, 56000 },{ 23000, 22600, 31950 },{ 16000, 15600, 20400 } }, + { { 21, 9, 9, 1 },{ 21, 7, 5, 1 },{ 21, 7, 5, 1 } }, 1, 0, 0 }, + + { 128000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 55000, 50000, 56000 },{ 36000, 36000, 56000 },{ 27000, 27000, 31950 } }, + { { 21, 11, 9, 1 },{ 21, 9, 7, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, + + { 160000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 74000, 70900, 112000 },{ 41000, 40050, 56000 },{ 35000, 34050, 56000 } }, + { { 21, 11, 11, 1 },{ 21, 9, 9, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, + + { 192000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 90000, 87900, 112000 },{ 50000, 48050, 56000 },{ 42000, 41050, 56000 } }, + { { 21, 11, 11, 1 },{ 21, 9, 9, 1 },{ 21, 7, 7, 1 } }, 1, 0, 0 }, + + { 256000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 90000, 85000, 112000 },{ 70000, 69000, 112000 },{ 50000, 48950, 56000 },{ 36400, 35600, 56000 } }, + { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 256000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 84650, 83000, 112000 },{ 65850, 64550, 56000 },{ 47000, 46100, 48000 },{ 28200, 27650, 40000 } }, + { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 256000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 76300, 73550, 112000 },{ 59350, 57200, 56000 },{ 42400, 40850, 48000 },{ 25450, 24500, 40000 } }, + { { 31, 11, 11, 1 },{ 1, 1, 1, 1 }, { 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 384000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 100000, 100000, 128000 },{ 79850, 79850, 104000 },{ 66600, 66600, 104000 } }, + { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 384000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 105350, 103300, 112000 },{ 75200, 73750, 96000 },{ 45100, 44250, 48000 } }, + { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 384000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 124300, 121550, 128000 },{ 96700, 94550, 112000 },{ 69050, 67500, 96000 },{ 41450, 40500, 48000 } }, + { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 512000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 }, {118450, 118450, 128000 } }, + { { 31, 1, 1, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, + + { 512000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 124000, 124000, 128000 },{ 124000, 124000, 128000 },{ 125200, 118450, 128000 },{ 76300, 73000, 128000 } }, + { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, -const Word16 sns_1st_means_16k[2][16] = -{ - { /* TCX 20 */ - 14210, 19017, 14362, 9309, 5385, 2674, 1055, -211, -1407, -3059, -4393, -8597, -11180, -11756, -12131, -13281, - }, - { /* TCX 10*/ - 12018, 15915, 11089, 6015, 847, -705, -539, -1548, -893, -2163, -1806, -4189, -7017, -8670, -8874, -9480, - } + { 512000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 118000, 118000, 128000 },{ 118000, 118000, 128000 },{ 117200, 109250, 128000 },{ 72300, 69000, 128000 } }, + { { 31, 11, 11, 1 },{ 1, 1, 1, 1 },{ 1, 1, 1, 1 } }, 1, 2, 0 }, }; -const Word16 sns_1st_means_25k6[2][16] = +const ivas_spar_br_table_t ivas_spar_br_table_consts_fx[IVAS_SPAR_BR_TABLE_LEN] = /*ceilf(log2f)*/ { - { /* TCX 20 */ - 14973, 20323, 16461, 9554, 4017, 3103, 1602, 1694, -221, -1401, -6817, -10071, -11503, -11805, -13158, -16749, - }, - { /* TCX 10 */ - 15560, 19489, 14623, 5595, 2084, 1699, 775, -1312, -2195, -6101, -9078, -9465, -7825, -6603, -7281, -9960, - } -}; + /* When AGC is ON additional (AGC_BITS_PER_CH+1) bits may be taken from each core-coder channel + so minimum core-coder bitrate per channel can be min core-coder bitrates as per the table - AGC_BITS_PER_CH */ + { 13200, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 10000, 8150, 13150 } }, + { { 4, 0, 3, 0 },{ 4, 0, 2, 0 },{ 3, 0, 2, 0 } }, 0, 0, 0 }, -const Word16 sns_1st_means_32k[2][16] = + { 16400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 13200, 11350, 16350 } }, + { { 4, 0, 3, 0 },{ 4, 0, 2, 0 },{ 3, 0, 2, 0 } }, 0, 0, 0 }, + + { 24400, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 16400, 14850, 24350 } }, + { { 4, 0, 3, 0 },{ 4, 0, 2, 0 },{ 3, 0, 2, 0 } }, 0, 0, 0 }, + + { 32000, 0, SBA_FOA_ORDER, FB, 24000, 1, WYXZ, 1, 0, { { 24000, 20450, 31950 } }, + { { 5, 0, 3, 0 },{ 4, 0, 3, 0 },{ 4, 0, 2, 0 } }, 0, 0, 0 }, + + { 48000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 24000, 21000, 31950 },{ 16000, 15000, 20400 } }, + { { 4, 3, 3, 0 },{ 4, 3, 2, 0 },{ 3, 3, 2, 0 } }, 1, 0, 0 }, + + { 64000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 38000, 34050, 56000 },{ 16000, 15600, 20400 } },{ { 5, 3, 3, 0 },{ 4, 3, 3, 0 },{ 4, 3, 2, 0 } }, 1, 1, 0 }, + + { 80000, 0, SBA_FOA_ORDER, FB, 24000, 2, WYXZ, 0, 0, { { 46000, 43000, 56000 },{ 24000, 23000, 31950 } }, + { { 5, 3, 3, 0 },{ 4, 3, 3, 0 },{ 4, 3, 2, 0 } }, 1, 0, 0 }, + + { 96000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 47000, 42600, 56000 },{ 23000, 22600, 31950 },{ 16000, 15600, 20400 } }, + { { 5, 4, 4, 0 },{ 5, 3, 3, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, + + { 128000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 55000, 50000, 56000 },{ 36000, 36000, 56000 },{ 27000, 27000, 31950 } }, + { { 5, 4, 4, 0 },{ 5, 4, 3, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, + + { 160000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 74000, 70900, 112000 },{ 41000, 40050, 56000 },{ 35000, 34050, 56000 } }, + { { 5, 4, 4, 0 },{ 5, 4, 4, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, + + { 192000, 0, SBA_FOA_ORDER, FB, 24000, 3, WYXZ, 0, 0, { { 90000, 87900, 112000 },{ 50000, 48050, 56000 },{ 42000, 41050, 56000 } }, + { { 5, 4, 4, 0 },{ 5, 4, 4, 0 },{ 5, 3, 3, 0 } }, 1, 0, 0 }, + + { 256000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 90000, 85000, 112000 },{ 70000, 69000, 112000 },{ 50000, 48950, 56000 },{ 36400, 35600, 56000 } }, + { { 5, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 256000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 84650, 83000, 112000 },{ 65850, 64550, 56000 },{ 47000, 46100, 48000 },{ 28200, 27650, 40000 } }, + { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 256000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 76300, 73550, 112000 },{ 59350, 57200, 56000 },{ 42400, 40850, 48000 },{ 25450, 24500, 40000 } }, + { { 5, 4, 4, 0 },{ 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 384000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 100000, 100000, 128000 },{ 79850, 79850, 104000 },{ 66600, 66600, 104000 } }, + { { 5, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 384000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 105350, 103300, 112000 },{ 75200, 73750, 96000 },{ 45100, 44250, 48000 } }, + { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 384000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 124300, 121550, 128000 },{ 96700, 94550, 112000 },{ 69050, 67500, 96000 },{ 41450, 40500, 48000 } }, + { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 512000, 0, SBA_FOA_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 128000, 128000, 128000 },{ 128000, 128000, 128000 },{ 128000, 128000, 128000 }, {118450, 118450, 128000 } }, + { { 5, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 512000, 0, SBA_HOA2_ORDER, FB, 24000, 4, WYXZ, 0, 0,{ { 124000, 124000, 128000 },{ 124000, 124000, 128000 },{ 125200, 118450, 128000 },{ 76300, 73000, 128000 } }, + { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, + + { 512000, 0, SBA_HOA3_ORDER, FB, 24000, 4, WYXZ, 0, 0, { { 118000, 118000, 128000 },{ 118000, 118000, 128000 },{ 117200, 109250, 128000 },{ 72300, 69000, 128000 } }, + { { 5, 4, 4, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }, 1, 2, 0 }, +}; +const ivas_freq_models_t ivas_arith_pred_r_consts[TOTAL_PRED_QUANT_STRATS_ARITH] = { - { /* TCX 20 */ - 15041, 20603, 16969, 10289, 4973, 4283, 3003, 3316, 1684, -259, -6614, -9535, -10363, -11834, -16625, -24930, + /* entry for 1 quantization points */ + { + /* pred_R real */ + { + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + }, + /* pred_R real differential */ + { + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + }, + /* pred_R real : values for general and differential */ + { 0 },{ 0 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 }, - { /* TCX 10 */ - 16510, 20660, 16025, 7224, 3921, 3868, 2623, 742, -1316, -6269, -8284, -7288, -6380, -8410, -13351, -20277, + /* entry for 7 quantization points for br_table_idx >= 2 */ + { + /* pred_R real */ + { + { 0,546,1092,2184,8740,2184,1092,546, }, + { 0,1779,2116,2516,3562,2516,2116,1779, }, + { 0,1848,2614,5229,2614,1848,1307,924, }, + { 0,924,1307,1848,2614,5229,2614,1848, }, + }, + /* pred_R real differential */ + { + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, }, + }, + /* pred_R real : values for general and differential */ + { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 15 quantization points for br_table_idx >= 2 */ + { + /* pred_R real */ + { + { 0,32,64,128,257,514,1028,2056,8226,2056,1028,514,257,128,64,32, }, + { 0,565,672,799,950,1130,1344,1598,2268,1598,1344,1130,950,799,672,565, }, + { 0,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353,250,176, }, + { 0,176,250,353,500,707,1000,1414,2000,4010,2000,1414,1000,707,500,353, }, + }, + /* pred_R real differential */ + { + { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, + { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, + { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, + { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, }, + }, + /* pred_R real : values for general and differential */ + { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, + { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 21 quantization points for br_table_idx >= 2 */ + { + /* pred_R real */ + { + { 0,4,8,16,32,64,128,256,512,1024,2049,8198,2049,1024,512,256,128,64,32,16,8,4, }, + { 0,292,348,414,492,585,696,828,984,1171,1392,1980,1392,1171,984,828,696,585,492,414,348,292, }, + { 0,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119,84,59, }, + { 0,59,84,119,168,238,336,476,673,952,1346,1904,3817,1904,1346,952,673,476,336,238,168,119, }, + }, + /* pred_R real differential */ + { + { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, + { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, + { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, + { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, + }, + /* pred_R real : values for general and differential */ + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 31 quantization points */ + { + /* pred real */ + { + { 0,1,1,1,1,2,4,8,16,32,64,128,256,512,1024,2048,8188,2048,1024,512,256,128,64,32,16,8,4,2,1,1,1,1, }, + { 0,110,131,156,186,221,263,313,373,443,527,627,746,887,1055,1255,1798,1255,1055,887,746,627,527,443,373,313,263,221,186,156,131,110, }, + { 0,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20,14,10, }, + { 0,10,14,20,29,41,58,82,116,164,233,329,466,659,932,1318,1864,3738,1864,1318,932,659,466,329,233,164,116,82,58,41,29,20, } + }, + /* pred real differential */ + { + { 0,1,1,1,1,1,1,1,1,1,3,12,39,125,397,1260,12694,1260,397,125,39,12,3,1,1,1,1,1,1,1,1,1, }, + { 0,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1, }, + { 0,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1,1,1, }, + { 0,1,1,1,2,3,6,11,20,37,66,117,210,374,667,1189,2118,6740,2118,1189,667,374,210,117,66,37,20,11,6,3,2,1, } + }, + /* pred real : values for general and differential */ + { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, + { -15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, + /* pred real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 7 quantization points for br_table_idx < 2 */ + { + /* pred_R real */ + { + { 0,327,778,1851,10472,1851,778,327, }, + { 0,1057,1630,2514,5982,2514,1630,1057, }, + { 0,1668,2572,6122,2572,1668,1081,701, }, + { 0,701,1081,1668,2572,6122,2572,1668, }, + }, + /* pred_R real differential */ + { + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, }, + }, + /* pred_R real : values for general and differential */ + { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 15 quantization points for br_table_idx < 2 */ + { + /* pred real */ + { + { 0,9,23,56,133,318,757,1800,10192,1800,757,318,133,56,23,9, }, + { 0,156,240,371,573,883,1363,2102,5008,2102,1363,883,573,371,240,156, }, + { 0,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241,156,101, }, + { 0,101,156,241,372,575,886,1367,2109,5027,2109,1367,886,575,372,241, } + }, + /* pred real differential */ + { + { 0,1,3,12,39,125,397,1260,12710,1260,397,125,39,12,3,1, }, + { 0,66,119,212,378,674,1201,2140,6804,2140,1201,674,378,212,119,66, }, + { 0,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119,67,37, }, + { 0,37,67,119,212,379,675,1203,2144,6816,2144,1203,675,379,212,119, } + }, + /* pred real : values for general and differential */ + {-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7}, + { -7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7 }, + /* pred real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 21 quantization points for br_table_idx < 2 */ + { + /* pred_R real */ + { + { 0,1,1,4,9,23,56,133,318,756,1799,10184,1799,756,318,133,56,23,9,4,1,1, }, + { 0,41,64,98,152,234,362,558,861,1329,2049,4888,2049,1329,861,558,362,234,152,98,64,41, }, + { 0,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64,41,26, }, + { 0,26,41,64,98,152,235,362,559,862,1330,2051,4891,2051,1330,862,559,362,235,152,98,64, }, + }, + /* pred_R real differential */ + { + { 0,1,1,1,1,3,12,39,125,397,1260,12704,1260,397,125,39,12,3,1,1,1,1, }, + { 0,11,20,37,66,118,210,375,668,1191,2122,6748,2122,1191,668,375,210,118,66,37,20,11, }, + { 0,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20,11,6, }, + { 0,6,11,20,37,66,118,210,375,668,1191,2123,6751,2123,1191,668,375,210,118,66,37,20, }, + }, + /* pred_R real : values for general and differential */ + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + { -10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10 }, + /* pred_R real : num dyn models for general and differential */ + 4, 4 } }; - -/*----------------------------------------------------------------------* - * MC ParamUpmix ROM tables - *-----------------------------------------------------------------------*/ - -const Word16 ivas_param_upmx_mx_qmap[33] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0 -}; - - -const Word32 release_cnst_table[4][201] = // Q31 +const ivas_freq_models_t ivas_arith_drct_r_consts[TOTAL_DRCT_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ { + /* drct real */ { - 1913946752, - 1919716352, - 1925351680, - 1930855552, - 1936230784, - 1941479808, - 1946605312, - 1951609728, - 1956495744, - 1961265792, - 1965922304, - 1970467584, - 1974904320, - 1979234560, - 1983460736, - 1987585024, - 1991609856, - 1995537280, - 1999369344, - 2003108480, - 2006756480, - 2010315520, - 2013787520, - 2017174528, - 2020478464, - 2023701248, - 2026844672, - 2029910656, - 2032900992, - 2035817344, - 2038661376, - 2041435008, - 2044139648, - 2046777088, - 2049348864, - 2051856384, - 2054301440, - 2056685312, - 2059009536, - 2061275520, - 2063484672, - 2065638272, - 2067737856, - 2069784448, - 2071779584, - 2073724416, - 2075620096, - 2077467904, - 2079268992, - 2081024512, - 2082735488, - 2084403200, - 2086028416, - 2087612544, - 2089156352, - 2090660864, - 2092127104, - 2093555968, - 2094948480, - 2096305408, - 2097627776, - 2098916352, - 2100172032, - 2101395584, - 2102587776, - 2103749504, - 2104881408, - 2105984384, - 2107059072, - 2108106112, - 2109126400, - 2110120448, - 2111088896, - 2112032512, - 2112951808, - 2113847552, - 2114720128, - 2115570304, - 2116398592, - 2117205504, - 2117991552, - 2118757504, - 2119503616, - 2120230400, - 2120938496, - 2121628288, - 2122300288, - 2122954880, - 2123592576, - 2124213760, - 2124818944, - 2125408384, - 2125982592, - 2126541952, - 2127086848, - 2127617664, - 2128134656, - 2128638336, - 2129128832, - 2129606784, - 2130072192, - 2130525568, - 2130967296, - 2131397376, - 2131816448, - 2132224640, - 2132622080, - 2133009408, - 2133386496, - 2133753856, - 2134111744, - 2134460288, - 2134799744, - 2135130368, - 2135452416, - 2135766144, - 2136071680, - 2136369152, - 2136659072, - 2136941312, - 2137216256, - 2137484160, - 2137744896, - 2137998976, - 2138246400, - 2138487424, - 2138722176, - 2138950656, - 2139173376, - 2139390208, - 2139601408, - 2139807104, - 2140007424, - 2140202624, - 2140392576, - 2140577664, - 2140758016, - 2140933504, - 2141104512, - 2141271040, - 2141433216, - 2141591168, - 2141745024, - 2141894912, - 2142040832, - 2142182912, - 2142321408, - 2142456192, - 2142587392, - 2142715264, - 2142839808, - 2142961152, - 2143079296, - 2143194240, - 2143306240, - 2143415424, - 2143521664, - 2143625216, - 2143725952, - 2143824128, - 2143919744, - 2144012800, - 2144103424, - 2144191744, - 2144277760, - 2144361472, - 2144443136, - 2144522496, - 2144599936, - 2144675200, - 2144748544, - 2144820096, - 2144889600, - 2144957440, - 2145023488, - 2145087744, - 2145150336, - 2145211264, - 2145270656, - 2145328512, - 2145384832, - 2145439616, - 2145493120, - 2145545088, - 2145595776, - 2145645056, - 2145693184, - 2145739904, - 2145785472, - 2145829888, - 2145873152, - 2145915136, - 2145956224, - 2145996032, - 2146034944, - 2146072832, - 2146109696, - 2146145664, - 2146180608, - 2146214656, - 2146247808, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + }, + /* drct real differential */ + { + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + }, + /* drct real : values for general and differential */ + {0},{ 0 }, + /* drct real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 7 quantization points */ + { /* drct real */ + { + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,988,1244,1568,1976,2489,3136,4983, }, + { 0,2111,2262,2425,2788,2425,2262,2111, }, + }, + /* drct real differential */ + { + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, }, + }, + /* drct real : values for general and differential */ + { -3,-2,-1,0,1,2,3 },{ -3,-2,-1,0,1,2,3 }, + /* drct real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 9 quantization points */ + { + /* drct real */ + { + { 0,39,125,397,1263,12736,1263,397,125,39, }, + { 0,397,708,1262,2250,7150,2250,1262,708,397, }, + { 0,573,722,909,1146,1444,1819,2292,2888,4591, }, + { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, }, + /* drct real differential */ { - 2027355264, - 2030408704, - 2033386624, - 2036290944, - 2039123328, - 2041885440, - 2044578944, - 2047205376, - 2049766528, - 2052263680, - 2054698496, - 2057072384, - 2059387008, - 2061643520, - 2063843328, - 2065987968, - 2068078720, - 2070116864, - 2072103552, - 2074040192, - 2075927936, - 2077767936, - 2079561472, - 2081309568, - 2083013376, - 2084673920, - 2086292352, - 2087869696, - 2089406976, - 2090905216, - 2092365184, - 2093788032, - 2095174528, - 2096525824, - 2097842432, - 2099125632, - 2100375808, - 2101594240, - 2102781312, - 2103938048, - 2105065216, - 2106163456, - 2107233536, - 2108276096, - 2109292032, - 2110281728, - 2111246080, - 2112185728, - 2113101056, - 2113992960, - 2114861824, - 2115708288, - 2116532992, - 2117336448, - 2118119168, - 2118881792, - 2119624704, - 2120348416, - 2121053440, - 2121740288, - 2122409344, - 2123061120, - 2123696128, - 2124314624, - 2124917120, - 2125504128, - 2126075776, - 2126632832, - 2127175296, - 2127703808, - 2128218624, - 2128720000, - 2129208448, - 2129684352, - 2130147712, - 2130599168, - 2131038976, - 2131467264, - 2131884416, - 2132290816, - 2132686592, - 2133072256, - 2133447680, - 2133813504, - 2134169856, - 2134516864, - 2134854784, - 2135184000, - 2135504640, - 2135816960, - 2136121216, - 2136417536, - 2136706048, - 2136987136, - 2137260928, - 2137527552, - 2137787264, - 2138040192, - 2138286592, - 2138526464, - 2138760192, - 2138987776, - 2139209472, - 2139425408, - 2139635712, - 2139840512, - 2140039936, - 2140234240, - 2140423424, - 2140607744, - 2140787200, - 2140962048, - 2141132288, - 2141298048, - 2141459584, - 2141616896, - 2141769984, - 2141919232, - 2142064512, - 2142205952, - 2142343808, - 2142478080, - 2142608768, - 2142736128, - 2142860032, - 2142980864, - 2143098368, - 2143212928, - 2143324544, - 2143433088, - 2143538944, - 2143641984, - 2143742336, - 2143840000, - 2143935232, - 2144027904, - 2144118144, - 2144206080, - 2144291712, - 2144375168, - 2144456320, - 2144535424, - 2144612480, - 2144687488, - 2144760448, - 2144831616, - 2144900992, - 2144968448, - 2145034112, - 2145098112, - 2145160448, - 2145221248, - 2145280256, - 2145337856, - 2145393920, - 2145448576, - 2145501696, - 2145553536, - 2145603968, - 2145653120, - 2145700992, - 2145747456, - 2145792896, - 2145837056, - 2145880064, - 2145922048, - 2145962880, - 2146002560, - 2146041344, - 2146078976, - 2146115712, - 2146151424, - 2146186240, - 2146220160, - 2146253184, - 2146285312, - 2146316672, - 2146347136, - 2146376832, - 2146405760, - 2146433920, - 2146461440, - 2146488192, - 2146514176, - 2146539520, - 2146564224, - 2146588160, - 2146611584, - 2146634368, - 2146656640, - 2146678272, - 2146699264, - 2146719744, - 2146739712, - 2146759168, - 2146778112, - 2146796544, - 2146814464, - 2146832000, - 2146849024, - 2146865664, + { 0,39,125,397,1263,12736,1263,397,125,39, }, + { 0,397,708,1262,2250,7150,2250,1262,708,397, }, + { 0,716,1276,2274,7225,2274,1276,716,402,225, }, + { 0,225,402,716,1276,2274,7225,2274,1276,716, } + }, + /* drct real : values for general and differential */ + { -4,-3,-2,-1,0,1,2,3,4 },{ -4,-3,-2,-1,0,1,2,3,4 }, + /* drct real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 11 quantization points */ + { + /* drct real */ + { + { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, + { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, + { 0,343,433,546,687,866,1092,1375,1733,2184,2751,4374, }, + { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, + }, + /* drct real differential */ + { + { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, + { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, + { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, + { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, + }, + /* drct real : values for general and differential */ + { -5,-4,-3,-2,-1,0,1,2,3,4,5 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, + /* drct real : num dyn models for general and differential */ + 4, 4 + } +}; + +const ivas_freq_models_t ivas_arith_decd_r_consts[TOTAL_DECD_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ + { + /* decd real */ + { + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + }, + /* decd real differential */ + { + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, + { 0,16384, }, }, + /* decd real : values for general and differential */ + { 0 },{ 0 }, + /* decd real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 3 quantization points */ + { + /* decd real */ { - 2086555136, - 2088125824, - 2089656576, - 2091148416, - 2092602240, - 2094018944, - 2095399680, - 2096745088, - 2098056192, - 2099333888, - 2100578816, - 2101792000, - 2102974080, - 2104125824, - 2105248128, - 2106341760, - 2107407232, - 2108445440, - 2109456896, - 2110442496, - 2111402624, - 2112338176, - 2113249664, - 2114137728, - 2115002880, - 2115845760, - 2116666880, - 2117466880, - 2118246272, - 2119005568, - 2119745280, - 2120465920, - 2121167872, - 2121851776, - 2122517888, - 2123166976, - 2123799168, - 2124414976, - 2125014912, - 2125599360, - 2126168704, - 2126723200, - 2127263360, - 2127789568, - 2128302208, - 2128801408, - 2129287808, - 2129761536, - 2130222976, - 2130672512, - 2131110272, - 2131536768, - 2131952128, - 2132356736, - 2132750848, - 2133134720, - 2133508736, - 2133872896, - 2134227584, - 2134573184, - 2134909696, - 2135237504, - 2135556736, - 2135867648, - 2136170624, - 2136465536, - 2136752896, - 2137032832, - 2137305344, - 2137570816, - 2137829376, - 2138081280, - 2138326528, - 2138565504, - 2138798080, - 2139024768, - 2139245440, - 2139460480, - 2139669888, - 2139873792, - 2140072320, - 2140265856, - 2140454144, - 2140637696, - 2140816384, - 2140990464, - 2141159936, - 2141325056, - 2141485824, - 2141642368, - 2141794944, - 2141943424, - 2142088064, - 2142228992, - 2142366208, - 2142499840, - 2142630016, - 2142756736, - 2142880128, - 2143000448, - 2143117440, - 2143231488, - 2143342592, - 2143450752, - 2143556096, - 2143658624, - 2143758592, - 2143855872, - 2143950592, - 2144043008, - 2144132864, - 2144220416, - 2144305664, - 2144388608, - 2144469504, - 2144548224, - 2144624896, - 2144699648, - 2144772352, - 2144843264, - 2144912256, - 2144979328, - 2145044864, - 2145108480, - 2145170560, - 2145231104, - 2145289856, - 2145347200, - 2145403008, - 2145457408, - 2145510400, - 2145561984, - 2145612160, - 2145661056, - 2145708672, - 2145755136, - 2145800192, - 2145844224, - 2145887104, - 2145928832, - 2145969408, - 2146008960, - 2146047616, - 2146085120, - 2146121600, - 2146157184, - 2146191872, - 2146225664, - 2146258560, - 2146290560, - 2146321792, - 2146352128, - 2146381696, - 2146410496, - 2146438528, - 2146465920, - 2146492416, - 2146518400, - 2146543616, - 2146568192, - 2146592128, - 2146615424, - 2146638080, - 2146660224, - 2146681728, - 2146702720, - 2146723072, - 2146743040, - 2146762368, - 2146781184, - 2146799616, - 2146817408, - 2146834816, - 2146851840, - 2146868352, - 2146884352, - 2146900096, - 2146915328, - 2146930176, - 2146944640, - 2146958720, - 2146972416, - 2146985856, - 2146998784, - 2147011456, - 2147023872, - 2147035904, - 2147047552, - 2147058944, - 2147070080, - 2147080832, - 2147091456, - 2147101696, - 2147111680, - 2147121408, - 2147130880, - 2147140096, - 2147149056, - 2147157760, - 2147166336, - 2147174656, + { 0,11917,2978,1489, }, + { 0,8840,4419,3125, }, + { 0,4567,7250,4567, }, + { 0,5203,5978,5203, }, + }, + /* decd real differential */ + { + { 0,1356,13672,1356, }, + { 0,3166,10052,3166, }, + { 0,10984,3459,1941, }, + { 0,1941,3459,10984, }, + }, + /* decd real : values for general and differential */ + { 0,1,2 },{-1,0,1}, + /* decd real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 5 quantization points */ + { + /* decd real */ + { + { 0,11157,2788,1394,697,348, }, + { 0,7186,3592,2540,1796,1270, }, + { 0,2512,3166,5028,3166,2512, }, + { 0,3048,3267,3754,3267,3048, }, + }, + /* decd real differential */ + { + { 0,406,1289,12994,1289,406, }, + { 0,1460,2601,8262,2601,1460, }, + { 0,2707,8599,2707,1519,852, }, + { 0,852,1519,2707,8599,2707, }, + }, + /* decd real : values for general and differential */ + { 0,1,2,3,4 },{ -2,-1,0,1,2 }, + /* decd real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 7 quantization points */ + { + /* decd real */ + { + { 0,10983,2744,1372,686,343,171,85, }, + { 0,6573,3285,2322,1642,1161,821,580, }, + { 0,1603,2020,2546,4046,2546,2020,1603, }, + { 0,2111,2262,2425,2788,2425,2262,2111, }, }, + /* decd real differential */ { - 2106670080, - 2107727232, - 2108757120, - 2109760640, - 2110738432, - 2111691008, - 2112619136, - 2113523328, - 2114404352, - 2115262592, - 2116098816, - 2116913408, - 2117707136, - 2118480256, - 2119233536, - 2119967360, - 2120682240, - 2121378688, - 2122057088, - 2122717952, - 2123361792, - 2123988992, - 2124599936, - 2125195136, - 2125774848, - 2126339584, - 2126889728, - 2127425536, - 2127947520, - 2128456064, - 2128951296, - 2129433856, - 2129903744, - 2130361600, - 2130807424, - 2131241728, - 2131664768, - 2132076928, - 2132478208, - 2132869248, - 2133250048, - 2133620992, - 2133982208, - 2134334080, - 2134676864, - 2135010688, - 2135335936, - 2135652608, - 2135961088, - 2136261504, - 2136554112, - 2136839168, - 2137116800, - 2137387136, - 2137650560, - 2137907072, - 2138156928, - 2138400256, - 2138637184, - 2138867968, - 2139092864, - 2139311744, - 2139524992, - 2139732736, - 2139934976, - 2140131968, - 2140323840, - 2140510720, - 2140692736, - 2140870016, - 2141042688, - 2141210752, - 2141374592, - 2141534080, - 2141689344, - 2141840640, - 2141987968, - 2142131456, - 2142271232, - 2142407424, - 2142539904, - 2142669056, - 2142794752, - 2142917248, - 2143036544, - 2143152640, - 2143265792, - 2143375872, - 2143483264, - 2143587712, - 2143689472, - 2143788544, - 2143885056, - 2143979136, - 2144070656, - 2144159872, - 2144246656, - 2144331264, - 2144413568, - 2144493824, - 2144571904, - 2144647936, - 2144722048, - 2144794240, - 2144864512, - 2144932864, - 2144999552, - 2145064448, - 2145127680, - 2145189248, - 2145249152, - 2145307520, - 2145364480, - 2145419776, - 2145473792, - 2145526272, - 2145577472, - 2145627264, - 2145675776, - 2145723008, - 2145768960, - 2145813760, - 2145857408, - 2145899904, - 2145941376, - 2145981696, - 2146020864, - 2146059136, - 2146096384, - 2146132608, - 2146167936, - 2146202368, - 2146235776, - 2146268416, - 2146300160, - 2146331136, - 2146361216, - 2146390528, - 2146419200, - 2146446976, - 2146474112, - 2146500480, - 2146526208, - 2146551168, - 2146575488, - 2146599296, - 2146622464, - 2146644864, - 2146666880, - 2146688128, - 2146708992, - 2146729216, - 2146748928, - 2146768128, - 2146786816, - 2146805120, - 2146822784, - 2146840064, - 2146856960, - 2146873344, - 2146889216, - 2146904832, - 2146919936, - 2146934656, - 2146948992, - 2146962944, - 2146976640, - 2146989824, - 2147002752, - 2147015296, - 2147027584, - 2147039488, - 2147051136, - 2147062400, - 2147073408, - 2147084160, - 2147094528, - 2147104768, - 2147114624, - 2147124352, - 2147133696, - 2147142912, - 2147151744, - 2147160448, - 2147168896, - 2147177088, - 2147185152, - 2147192960, - 2147200512, - 2147207936, - 2147215104, - 2147222144, - 2147229056, - 2147235712, - 2147242112, - 2147248384, - 2147254656, - 2147260544, - 2147266432, - 2147272064, - 2147277568, + { 0,125,399,1269,12798,1269,399,125, }, + { 0,744,1327,2365,7512,2365,1327,744, }, + { 0,1354,2413,7664,2413,1354,760,426, }, + { 0,426,760,1354,2413,7664,2413,1354, } + }, + /* decd real : values for general and differential */ + { 0,1,2,3,4,5,6 },{ -3,-2,-1,0,1,2,3 }, + /* decd real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 9 quantization points */ + { /* decd real */ + { + { 0,10941,2734,1367,683,341,170,85,42,21, }, + { 0,6305,3150,2227,1575,1113,787,556,393,278, }, + { 0,1101,1388,1749,2203,3502,2203,1749,1388,1101, }, + { 0,1587,1701,1824,1955,2250,1955,1824,1701,1587, }, + }, + /* decd real differential */ + { + { 0,39,125,397,1263,12736,1263,397,125,39, }, + { 0,397,708,1262,2250,7150,2250,1262,708,397, }, + { 0,716,1276,2274,7225,2274,1276,716,402,225, }, + { 0,225,402,716,1276,2274,7225,2274,1276,716, } + }, + /* decd real : values for general and differential */ + { 0,1,2,3,4,5,6,7,8 },{ -4,-3,-2,-1,0,1,2,3,4 }, + /* decd real : num dyn models for general and differential */ + 4, 4 + }, + /* entry for 11 quantization points */ + { + /* decd real */ + { + { 0,10932,2731,1365,682,341,170,85,42,21,10,5, }, + { 0,6181,3086,2182,1543,1091,771,545,385,272,192,136, }, + { 0,790,995,1254,1580,1991,3164,1991,1580,1254,995,790, }, + { 0,1254,1344,1441,1544,1655,1908,1655,1544,1441,1344,1254, }, + }, + /* decd real differential */ + { + { 0,12,39,125,397,1261,12716,1261,397,125,39,12, }, + { 0,217,387,689,1229,2190,6960,2190,1229,689,387,217, }, + { 0,389,694,1236,2203,7000,2203,1236,694,389,218,122, }, + { 0,122,218,389,694,1236,2203,7000,2203,1236,694,389, }, + }, + /* decd real : values for general and differential */ + { 0,1,2,3,4,5,6,7,8,9,10 },{ -5,-4,-3,-2,-1,0,1,2,3,4,5 }, + /* decd real : num dyn models for general and differential */ + 4, 4 + } +}; + +const ivas_huff_models_t ivas_huff_pred_r_consts[TOTAL_PRED_QUANT_STRATS_HUFF] = +{ + /* entry for 1 quantization points for br_table_idx */ + {{{ 0 }}, {{ 0 }}}, + /* entry for 7 quantization points for br_table_idx */ + { + /* pred_R codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, + /* pred_R differential codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 }, }, + }, + /* entry for 15 quantization points for br_table_idx */ + { + /* pred_r codebook */ + { { -7,4,2 },{ -6,4,3 },{ -5, 4, 4 },{ -4, 4, 5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 }, + { 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 } }, + /* pred_r differential codebook */ + { { -7,4,2 },{ -6,4,3 },{ -5, 4, 4 },{ -4, 4, 5 },{ -3,4,6 },{ -2,4,7 },{ -1,4,8 }, + { 0,3,0 },{ 1,4,9 },{ 2,4,10 },{ 3,4,11 },{ 4,4,12 },{ 5,4,13 },{ 6,4,14 },{ 7,4,15 } }, + }, + /* entry for 21 quantization points for br_table_idx=0 */ + { + /* pred_r codebook */ + { {-10,5,22},{-9,5,23},{-8,5,24},{-7,5,25},{-6,5,26}, { -5, 4, 0 },{ -4, 4, 1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 }, + { 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{6,5,27},{7,5,28},{8,5,29},{9,5,30},{10,5,31} }, + /* pred_r differential codebook */ + { { -10,5,22 },{ -9,5,23 },{ -8,5,24 },{ -7,5,25 },{ -6,5,26 },{ -5, 4, 0 },{ -4, 4, 1 },{ -3,4,2 },{ -2,4,3 },{ -1,4,4 }, + { 0,4,5 },{ 1,4,6 },{ 2,4,7 },{ 3,4,8 },{ 4,4,9 },{ 5,4,10 },{ 6,5,27 },{ 7,5,28 },{ 8,5,29 },{ 9,5,30 },{ 10,5,31 } }, + }, + + /* entry for 31 quantization points for br_table_idx>0 */ + { + /* pred_r codebook */ + { {-15,5,2},{-14,5,3},{-13,5,4},{-12,5,5},{-11,5,6}, { -10,5,7 },{ -9,5,8 },{ -8,5,9 }, + { -7,5,10 },{ -6,5,11 },{ -5, 5, 12 },{ -4, 5, 13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 }, + { 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 }, + { 8,5,24 },{ 9,5,25 },{ 10,5,26 },{11,5,27},{12,5,28},{13,5,29},{14,5,30},{15,5,31} }, + /* pred_r differential codebook */ + { { -15,5,2 },{ -14,5,3 },{ -13,5,4 },{ -12,5,5 },{ -11,5,6 },{ -10,5,7 },{ -9,5,8 },{ -8,5,9 }, + { -7,5,10 },{ -6,5,11 },{ -5, 5, 12 },{ -4, 5, 13 },{ -3,5,14 },{ -2,5,15 },{ -1,5,16 }, + { 0,4,0 },{ 1,5,17 },{ 2,5,18 },{ 3,5,19 },{ 4,5,20 },{ 5,5,21 },{ 6,5,22 },{ 7,5,23 }, + { 8,5,24 },{ 9,5,25 },{ 10,5,26 },{ 11,5,27 },{ 12,5,28 },{ 13,5,29 },{ 14,5,30 },{ 15,5,31 } }, + }, + }; + + const ivas_huff_models_t ivas_huff_drct_r_consts[TOTAL_DRCT_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ + {{{ 0 }}, {{ 0 }}}, + /* entry for 7 quantization points */ + { + /* drct_r codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, + /* drct_r differential codebook */ + { { -3,3,2 },{ -2,3,3 },{ -1,3,4 },{ 0,2,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, + }, + /* entry for 9 quantization points */ + { + /* drct_r codebook */ + { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, + /* drct_r differential codebook */ + { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, + }, + /* entry for 11 quantization points */ + { + /* drct_r codebook */ + { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, + /* drct_r differential codebook */ + { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, + }, +}; + +const ivas_huff_models_t ivas_huff_decd_r_consts[TOTAL_DECD_QUANT_STRATS] = +{ + /* entry for 1 quantization points */ + {{{ 0 }}, {{ 0 }}}, + /* entry for 3 quantization points */ + { + /* decd_r codebook */ + { { 0, 2, 2 },{ 1, 1, 0 },{ 2,2,3 } }, + /* decd_r differential codebook */ + { { -1, 2, 2 },{ 0, 1, 0 },{ 1,2,3 } }, + }, + /* entry for 5 quantization points */ + { + /* decd_r codebook */ + { { 0,3,6 },{ 1,2,0 },{ 2,2,1 },{ 3,2,2 },{ 4,3,7 } }, + /* decd_r differential codebook */ + { { -2,3,6 },{ -1,2,0 },{ 0,2,1 },{ 1,2,2 },{ 2,3,7 } }, + }, + /* entry for 7 quantization points */ + { + /* decd_r */ + { { 0, 3, 2 },{ 1, 3, 3 },{ 2,3,4 },{ 3,3,0 },{ 4,3,5 },{ 5,3,6 },{ 6,3,7 } }, + /* decd_r codebook differential codebook */ + { { -3, 3, 2 },{ -2, 3, 3 },{ -1,3,4 },{ 0,3,0 },{ 1,3,5 },{ 2,3,6 },{ 3,3,7 } }, + }, + /* entry for 9 quantization points */ + { + /* decd_r codebook */ + { { 0, 4, 14 },{ 1,3,0 },{ 2,3,1 },{ 3,3,2 },{ 4,3,3 },{ 5,3,4 },{ 6,3,5 },{ 7,3,6 },{ 8,4,15 } }, + /* decd_r differential codebook */ + { { -4, 4, 14 },{ -3,3,0 },{ -2,3,1 },{ -1,3,2 },{ 0,3,3 },{ 1,3,4 },{ 2,3,5 },{ 3,3,6 },{ 4,4,15 } }, + }, + /* entry for 11 quantization points */ + { + /* decd_r codebook */ + { { 0, 4, 10 },{ 1, 4, 11 },{ 2,4,12 },{ 3,3,0 },{ 4,3,1 },{ 5,3,2 },{ 6,3,3 },{ 7,3,4 },{ 8,4,13 },{ 9,4,14 },{ 10,4,15 } }, + /* decd_r differential codebook */ + { { -5, 4, 10 },{ -4, 4, 11 },{ -3,4,12 },{ -2,3,0 },{ -1,3,1 },{ 0,3,2 },{ 1,3,3 },{ 2,3,4 },{ 3,4,13 },{ 4,4,14 },{ 5,4,15 } }, + }, +}; + +/* DTX quantization and bitstream constants */ + +const Word16 dtx_pd_real_q_levels[3][3] = { { 7,7,7 },{ 7,7,0 },{ 3,0,0 } }; +const Word16 dtx_pr_real_q_levels[3][3] = { { 9,9,9 },{ 9,7,9 },{ 9,5,7 } }; +const Word16 pr_pr_idx_pairs[3][3][2] = { { { 0, 0 },{ 0, 0 },{ 0, 0 } },{ { 0, 0 },{ 0, 0 },{ 0, 0 } },{ { 0, 0 },{ 1, 3 },{ 0, 0 } } }; +const Word16 pr_pd_idx_pairs[3][3][2] = { { { 1, 1 },{ 2, 2 },{ 3, 3 } },{ { 1, 1 },{ 3, 2 },{ 2, 0 } },{ { 2, 1 },{ 0, 0 },{ 0, 0 } } }; + +const Word16 remix_order_set[1][DIRAC_MAX_ANA_CHANS] = { /* WYZX --> WYXZ... */ + { 0, 1, 3, 2, 4, 5, 6, 7, 8, 9, 10 } +}; + +const Word16 HOA_keep_ind[IVAS_SPAR_MAX_FB_IN_CHAN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15}; +const Word16 HOA_keep_ind_spar[IVAS_SPAR_MAX_CH] = {0, 1, 2, 3, 4, 8, 9, 10, 10, 10, 10}; +const Word16 HOA_keep_ind_spar512[IVAS_SPAR_MAX_CH] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + +/*----------------------------------------------------------------------* +* PCA ROM tables +*-----------------------------------------------------------------------*/ + +const Word32 ivas_pca_offset_index1[IVAS_PCA_N1 + 1] = +{ + 0, 1, 9, 61, 163, 359, 685, 1125, 1747, + 2519, 3521, 4713, 6183, 7883, 9809, 12093, 14633, 17575, + 20807, 24343, 28181, 32487, 37121, 42097, 47405, 53057, 59061, + 65421, 72137, 79205, 86625, 94415, 102345, 110629, 119263, 128017, + 137097, 146515, 156043, 165637, 175551, 185515, 195535, 205837, 216183, + 226545, 236911, 247273, 257619, 267921, 277941, 287905, 297819, 307413, + 316941, 326359, 335439, 344193, 352827, 361111, 369041, 376831, 384251, + 391319, 398035, 404395, 410399, 416051, 421359, 426335, 430969, 435275, + 439113, 442649, 445881, 448823, 451363, 453647, 455573, 457273, 458743, + 459935, 460937, 461709, 462331, 462771, 463097, 463293, 463395, 463447, + 463455, 463456 +}; + +const Word16 ivas_pca_offset_index2[2692] = +{ + 0, 1, 0, 1, 7, 8, 0, 1, 7, 19, + 33, 45, 51, 52, 0, 1, 9, 23, 41, 61, + 79, 93, 101, 102, 0, 1, 7, 21, 39, 61, + 85, 111, 135, 157, 175, 189, 195, 196, 0, 1, + 7, 19, 37, 59, 85, 115, 147, 179, 211, 241, + 267, 289, 307, 319, 325, 326, 0, 1, 7, 21, + 41, 65, 95, 127, 163, 201, 239, 277, 313, 345, + 375, 399, 419, 433, 439, 440, 0, 1, 7, 19, + 37, 61, 91, 125, 163, 203, 245, 289, 333, 377, + 419, 459, 497, 531, 561, 585, 603, 615, 621, 622, + 0, 1, 7, 21, 41, 67, 97, 133, 173, 217, + 263, 311, 361, 411, 461, 509, 555, 599, 639, 675, + 705, 731, 751, 765, 771, 772, 0, 1, 7, 19, + 37, 61, 91, 127, 167, 211, 259, 309, 363, 417, + 473, 529, 585, 639, 693, 743, 791, 835, 875, 911, + 941, 965, 983, 995, 1001, 1002, 0, 1, 7, 21, + 41, 67, 99, 135, 177, 223, 273, 327, 383, 443, + 503, 565, 627, 689, 749, 809, 865, 919, 969, 1015, + 1057, 1093, 1125, 1151, 1171, 1185, 1191, 1192, 0, 1, + 7, 19, 37, 61, 91, 127, 169, 215, 265, 319, + 377, 437, 501, 567, 633, 701, 769, 837, 903, 969, + 1033, 1093, 1151, 1205, 1255, 1301, 1343, 1379, 1409, 1433, + 1451, 1463, 1469, 1470, 0, 1, 7, 21, 41, 67, + 99, 137, 179, 227, 279, 335, 395, 459, 525, 595, + 667, 739, 813, 887, 961, 1033, 1105, 1175, 1241, 1305, + 1365, 1421, 1473, 1521, 1563, 1601, 1633, 1659, 1679, 1693, + 1699, 1700, 0, 1, 9, 23, 43, 69, 101, 139, + 183, 231, 285, 343, 405, 471, 541, 613, 689, 765, + 843, 923, 1003, 1083, 1161, 1237, 1313, 1385, 1455, 1521, + 1583, 1641, 1695, 1743, 1787, 1825, 1857, 1883, 1903, 1917, + 1925, 1926, 0, 1, 7, 21, 41, 67, 99, 137, + 179, 227, 281, 339, 401, 467, 537, 611, 687, 767, + 849, 931, 1015, 1099, 1185, 1269, 1353, 1435, 1517, 1597, + 1673, 1747, 1817, 1883, 1945, 2003, 2057, 2105, 2147, 2185, + 2217, 2243, 2263, 2277, 2283, 2284, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 285, 345, 409, 477, + 549, 625, 705, 787, 871, 957, 1045, 1135, 1225, 1315, + 1405, 1495, 1583, 1669, 1753, 1835, 1915, 1991, 2063, 2131, + 2195, 2255, 2309, 2359, 2403, 2441, 2473, 2499, 2519, 2533, + 2539, 2540, 0, 1, 7, 19, 39, 65, 97, 135, + 177, 225, 279, 337, 401, 469, 541, 617, 697, 781, + 867, 955, 1045, 1137, 1231, 1327, 1423, 1519, 1615, 1711, + 1805, 1897, 1987, 2075, 2161, 2245, 2325, 2401, 2473, 2541, + 2605, 2663, 2717, 2765, 2807, 2845, 2877, 2903, 2923, 2935, + 2941, 2942, 0, 1, 7, 21, 41, 67, 99, 137, + 181, 229, 283, 343, 407, 477, 551, 629, 711, 797, + 885, 977, 1071, 1167, 1265, 1365, 1465, 1565, 1667, 1767, + 1867, 1967, 2065, 2161, 2255, 2347, 2435, 2521, 2603, 2681, + 2755, 2825, 2889, 2949, 3003, 3051, 3095, 3133, 3165, 3191, + 3211, 3225, 3231, 3232, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 347, 413, 483, 559, 639, + 723, 811, 903, 997, 1093, 1193, 1295, 1399, 1503, 1609, + 1715, 1821, 1927, 2033, 2137, 2241, 2343, 2443, 2539, 2633, + 2725, 2813, 2897, 2977, 3053, 3123, 3189, 3249, 3305, 3355, + 3399, 3437, 3469, 3495, 3515, 3529, 3535, 3536, 0, 1, + 7, 21, 41, 67, 99, 137, 181, 231, 287, 349, + 415, 487, 563, 645, 731, 821, 915, 1011, 1111, 1213, + 1317, 1423, 1531, 1641, 1751, 1863, 1975, 2087, 2197, 2307, + 2415, 2521, 2625, 2727, 2827, 2923, 3017, 3107, 3193, 3275, + 3351, 3423, 3489, 3551, 3607, 3657, 3701, 3739, 3771, 3797, + 3817, 3831, 3837, 3838, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 285, 345, 411, 481, 557, 637, + 721, 809, 901, 997, 1097, 1199, 1305, 1413, 1523, 1635, + 1749, 1863, 1979, 2095, 2211, 2327, 2443, 2557, 2671, 2783, + 2893, 3001, 3107, 3209, 3309, 3405, 3497, 3585, 3669, 3749, + 3825, 3895, 3961, 4021, 4075, 4125, 4169, 4207, 4239, 4265, + 4285, 4299, 4305, 4306, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 347, 413, 485, 561, 643, + 729, 819, 913, 1011, 1113, 1217, 1325, 1435, 1547, 1663, + 1779, 1897, 2017, 2137, 2257, 2377, 2497, 2617, 2737, 2855, + 2971, 3087, 3199, 3309, 3417, 3521, 3623, 3721, 3815, 3905, + 3991, 4073, 4149, 4221, 4287, 4347, 4403, 4453, 4497, 4535, + 4567, 4593, 4613, 4627, 4633, 4634, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 415, 487, + 565, 647, 733, 825, 921, 1021, 1125, 1231, 1341, 1453, + 1569, 1687, 1807, 1929, 2051, 2175, 2299, 2425, 2551, 2677, + 2801, 2925, 3047, 3169, 3289, 3407, 3523, 3635, 3745, 3851, + 3955, 4055, 4151, 4243, 4329, 4411, 4489, 4561, 4627, 4689, + 4745, 4795, 4839, 4877, 4909, 4935, 4955, 4969, 4975, 4976, + 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, + 287, 349, 417, 489, 567, 649, 737, 829, 925, 1025, + 1129, 1237, 1349, 1463, 1581, 1701, 1823, 1947, 2073, 2201, + 2329, 2459, 2589, 2719, 2849, 2979, 3107, 3235, 3361, 3485, + 3607, 3727, 3845, 3959, 4071, 4179, 4283, 4383, 4479, 4571, + 4659, 4741, 4819, 4891, 4959, 5021, 5077, 5127, 5171, 5209, + 5241, 5267, 5287, 5301, 5307, 5308, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 417, 489, + 567, 651, 739, 831, 929, 1031, 1137, 1247, 1361, 1477, + 1597, 1719, 1843, 1969, 2097, 2227, 2359, 2491, 2625, 2759, + 2893, 3027, 3161, 3293, 3425, 3555, 3683, 3809, 3933, 4055, + 4175, 4291, 4405, 4515, 4621, 4723, 4821, 4913, 5001, 5085, + 5163, 5235, 5303, 5365, 5421, 5471, 5515, 5553, 5585, 5611, + 5631, 5645, 5651, 5652, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 569, 653, + 741, 835, 933, 1035, 1141, 1251, 1365, 1483, 1603, 1727, + 1853, 1983, 2115, 2249, 2383, 2519, 2657, 2795, 2933, 3071, + 3209, 3347, 3485, 3621, 3755, 3889, 4021, 4151, 4277, 4401, + 4521, 4639, 4753, 4863, 4969, 5071, 5169, 5263, 5351, 5435, + 5513, 5587, 5655, 5717, 5773, 5823, 5867, 5905, 5937, 5963, + 5983, 5997, 6003, 6004, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 569, 653, + 741, 835, 933, 1037, 1145, 1257, 1373, 1491, 1613, 1739, + 1867, 1997, 2131, 2267, 2405, 2543, 2683, 2825, 2967, 3109, + 3251, 3393, 3535, 3677, 3817, 3955, 4093, 4229, 4363, 4493, + 4621, 4747, 4869, 4987, 5103, 5215, 5323, 5427, 5525, 5619, + 5707, 5791, 5869, 5943, 6011, 6073, 6129, 6179, 6223, 6261, + 6293, 6319, 6339, 6353, 6359, 6360, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, + 569, 653, 743, 837, 935, 1039, 1147, 1259, 1375, 1495, + 1619, 1745, 1875, 2007, 2143, 2281, 2421, 2563, 2705, 2849, + 2993, 3139, 3285, 3431, 3577, 3723, 3867, 4011, 4153, 4295, + 4435, 4573, 4709, 4841, 4971, 5097, 5221, 5341, 5457, 5569, + 5677, 5781, 5879, 5973, 6063, 6147, 6225, 6299, 6367, 6429, + 6485, 6535, 6579, 6617, 6649, 6675, 6695, 6709, 6715, 6716, + 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, + 287, 349, 417, 491, 569, 653, 743, 837, 937, 1041, + 1149, 1261, 1377, 1497, 1621, 1749, 1879, 2013, 2149, 2287, + 2429, 2573, 2717, 2863, 3011, 3159, 3309, 3459, 3609, 3759, + 3909, 4057, 4205, 4351, 4495, 4639, 4781, 4919, 5055, 5189, + 5319, 5447, 5571, 5691, 5807, 5919, 6027, 6131, 6231, 6325, + 6415, 6499, 6577, 6651, 6719, 6781, 6837, 6887, 6931, 6969, + 7001, 7027, 7047, 7061, 7067, 7068, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, + 569, 653, 743, 837, 937, 1041, 1149, 1261, 1377, 1497, + 1621, 1749, 1881, 2015, 2153, 2293, 2435, 2579, 2725, 2873, + 3023, 3175, 3327, 3479, 3633, 3787, 3941, 4093, 4245, 4397, + 4547, 4695, 4841, 4985, 5127, 5267, 5405, 5539, 5671, 5799, + 5923, 6043, 6159, 6271, 6379, 6483, 6583, 6677, 6767, 6851, + 6929, 7003, 7071, 7133, 7189, 7239, 7283, 7321, 7353, 7379, + 7399, 7413, 7419, 7420, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 489, 567, 651, + 741, 835, 935, 1039, 1147, 1259, 1377, 1499, 1625, 1753, + 1885, 2021, 2159, 2301, 2445, 2591, 2739, 2889, 3041, 3195, + 3349, 3505, 3661, 3817, 3973, 4129, 4285, 4441, 4595, 4749, + 4901, 5051, 5199, 5345, 5489, 5631, 5769, 5905, 6037, 6165, + 6291, 6413, 6531, 6643, 6751, 6855, 6955, 7049, 7139, 7223, + 7301, 7373, 7441, 7503, 7559, 7609, 7653, 7691, 7723, 7749, + 7769, 7783, 7789, 7790, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, + 747, 843, 945, 1051, 1161, 1277, 1397, 1521, 1649, 1781, + 1915, 2053, 2195, 2339, 2485, 2635, 2787, 2941, 3095, 3251, + 3409, 3567, 3725, 3885, 4045, 4205, 4363, 4521, 4679, 4835, + 4989, 5143, 5295, 5445, 5591, 5735, 5877, 6015, 6149, 6281, + 6409, 6533, 6653, 6769, 6879, 6985, 7087, 7183, 7273, 7359, + 7439, 7513, 7581, 7643, 7699, 7749, 7793, 7831, 7863, 7889, + 7909, 7923, 7929, 7930, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, + 747, 843, 943, 1049, 1159, 1273, 1393, 1517, 1645, 1777, + 1913, 2051, 2193, 2337, 2485, 2635, 2787, 2941, 3097, 3255, + 3415, 3575, 3737, 3899, 4061, 4223, 4385, 4547, 4709, 4869, + 5029, 5187, 5343, 5497, 5649, 5799, 5947, 6091, 6233, 6371, + 6507, 6639, 6767, 6891, 7011, 7125, 7235, 7341, 7441, 7537, + 7627, 7713, 7793, 7867, 7935, 7997, 8053, 8103, 8147, 8185, + 8217, 8243, 8263, 8277, 8283, 8284, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, + 571, 655, 745, 841, 941, 1047, 1157, 1271, 1389, 1513, + 1641, 1773, 1907, 2045, 2187, 2331, 2479, 2629, 2783, 2939, + 3097, 3257, 3417, 3579, 3743, 3907, 4071, 4235, 4399, 4563, + 4727, 4891, 5055, 5217, 5377, 5537, 5695, 5851, 6005, 6155, + 6303, 6447, 6589, 6727, 6861, 6993, 7121, 7245, 7363, 7477, + 7587, 7693, 7793, 7889, 7979, 8063, 8143, 8217, 8285, 8347, + 8403, 8453, 8497, 8535, 8567, 8593, 8613, 8627, 8633, 8634, + 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, + 287, 349, 417, 491, 571, 657, 749, 845, 947, 1053, + 1165, 1281, 1401, 1527, 1657, 1791, 1929, 2069, 2213, 2361, + 2511, 2663, 2819, 2977, 3137, 3299, 3463, 3627, 3793, 3959, + 4125, 4293, 4461, 4629, 4795, 4961, 5127, 5291, 5455, 5617, + 5777, 5935, 6091, 6243, 6393, 6541, 6685, 6825, 6963, 7097, + 7227, 7353, 7473, 7589, 7701, 7807, 7909, 8005, 8097, 8183, + 8263, 8337, 8405, 8467, 8523, 8573, 8617, 8655, 8687, 8713, + 8733, 8747, 8753, 8754, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, + 747, 843, 943, 1049, 1159, 1275, 1395, 1519, 1647, 1779, + 1915, 2055, 2199, 2345, 2495, 2647, 2803, 2961, 3121, 3283, + 3447, 3613, 3779, 3947, 4115, 4285, 4455, 4625, 4795, 4965, + 5133, 5301, 5467, 5633, 5797, 5959, 6119, 6277, 6433, 6585, + 6735, 6881, 7025, 7165, 7301, 7433, 7561, 7685, 7805, 7921, + 8031, 8137, 8237, 8333, 8423, 8509, 8589, 8663, 8731, 8793, + 8849, 8899, 8943, 8981, 9013, 9039, 9059, 9073, 9079, 9080, + 0, 1, 7, 19, 39, 65, 97, 135, 179, 229, + 285, 347, 415, 489, 567, 651, 741, 835, 935, 1041, + 1151, 1265, 1385, 1509, 1637, 1769, 1905, 2045, 2189, 2335, + 2485, 2637, 2793, 2951, 3111, 3273, 3437, 3603, 3771, 3939, + 4109, 4279, 4451, 4623, 4795, 4967, 5139, 5309, 5479, 5647, + 5815, 5981, 6145, 6307, 6467, 6625, 6781, 6933, 7083, 7229, + 7373, 7513, 7649, 7781, 7909, 8033, 8153, 8267, 8377, 8483, + 8583, 8677, 8767, 8851, 8929, 9003, 9071, 9133, 9189, 9239, + 9283, 9321, 9353, 9379, 9399, 9411, 9417, 9418, 0, 1, + 7, 21, 41, 67, 99, 137, 181, 231, 287, 349, + 417, 491, 571, 657, 747, 843, 945, 1051, 1163, 1279, + 1399, 1525, 1655, 1789, 1927, 2069, 2213, 2361, 2513, 2667, + 2825, 2985, 3147, 3311, 3477, 3645, 3815, 3985, 4157, 4329, + 4503, 4677, 4851, 5025, 5199, 5371, 5543, 5713, 5883, 6051, + 6217, 6381, 6543, 6703, 6861, 7015, 7167, 7315, 7459, 7601, + 7739, 7873, 8003, 8129, 8249, 8365, 8477, 8583, 8685, 8781, + 8871, 8957, 9037, 9111, 9179, 9241, 9297, 9347, 9391, 9429, + 9461, 9487, 9507, 9521, 9527, 9528, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, + 571, 657, 749, 845, 947, 1055, 1167, 1285, 1407, 1533, + 1663, 1797, 1935, 2077, 2223, 2373, 2525, 2681, 2839, 3001, + 3165, 3331, 3499, 3669, 3839, 4011, 4185, 4359, 4533, 4709, + 4885, 5061, 5235, 5409, 5583, 5755, 5925, 6095, 6263, 6429, + 6593, 6755, 6913, 7069, 7221, 7371, 7517, 7659, 7797, 7931, + 8061, 8187, 8309, 8427, 8539, 8647, 8749, 8845, 8937, 9023, + 9103, 9177, 9245, 9307, 9363, 9413, 9457, 9495, 9527, 9553, + 9573, 9587, 9593, 9594, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 571, 655, + 745, 841, 941, 1047, 1157, 1273, 1393, 1517, 1647, 1781, + 1919, 2061, 2207, 2355, 2507, 2663, 2821, 2981, 3145, 3311, + 3479, 3649, 3821, 3993, 4167, 4341, 4517, 4693, 4869, 5045, + 5221, 5397, 5573, 5747, 5921, 6093, 6265, 6435, 6603, 6769, + 6933, 7093, 7251, 7407, 7559, 7707, 7853, 7995, 8133, 8267, + 8397, 8521, 8641, 8757, 8867, 8973, 9073, 9169, 9259, 9343, + 9423, 9497, 9565, 9627, 9683, 9733, 9777, 9815, 9847, 9873, + 9893, 9907, 9913, 9914, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, + 747, 843, 945, 1051, 1163, 1279, 1401, 1527, 1657, 1791, + 1929, 2071, 2217, 2367, 2519, 2675, 2835, 2997, 3161, 3327, + 3495, 3665, 3837, 4011, 4185, 4361, 4537, 4715, 4893, 5071, + 5249, 5427, 5603, 5779, 5953, 6127, 6299, 6469, 6637, 6803, + 6967, 7129, 7289, 7445, 7597, 7747, 7893, 8035, 8173, 8307, + 8437, 8563, 8685, 8801, 8913, 9019, 9121, 9217, 9307, 9393, + 9473, 9547, 9615, 9677, 9733, 9783, 9827, 9865, 9897, 9923, + 9943, 9957, 9963, 9964, 0, 1, 7, 21, 41, 67, + 99, 137, 181, 231, 287, 349, 417, 491, 571, 657, + 749, 845, 947, 1055, 1167, 1285, 1407, 1533, 1663, 1799, + 1939, 2083, 2229, 2379, 2533, 2689, 2849, 3011, 3177, 3345, + 3515, 3687, 3861, 4035, 4211, 4387, 4565, 4743, 4921, 5099, + 5277, 5455, 5633, 5809, 5985, 6159, 6333, 6505, 6675, 6843, + 7009, 7171, 7331, 7487, 7641, 7791, 7937, 8081, 8221, 8357, + 8487, 8613, 8735, 8853, 8965, 9073, 9175, 9271, 9363, 9449, + 9529, 9603, 9671, 9733, 9789, 9839, 9883, 9921, 9953, 9979, + 9999, 10013, 10019, 10020, 0, 1, 7, 19, 39, 65, + 97, 135, 179, 229, 285, 347, 415, 489, 567, 651, + 741, 837, 937, 1043, 1153, 1269, 1389, 1513, 1643, 1777, + 1915, 2057, 2203, 2351, 2503, 2659, 2817, 2979, 3143, 3309, + 3477, 3647, 3819, 3993, 4169, 4345, 4523, 4701, 4881, 5061, + 5241, 5421, 5601, 5779, 5957, 6133, 6309, 6483, 6655, 6825, + 6993, 7159, 7323, 7485, 7643, 7799, 7951, 8099, 8245, 8387, + 8525, 8659, 8789, 8913, 9033, 9149, 9259, 9365, 9465, 9561, + 9651, 9735, 9813, 9887, 9955, 10017, 10073, 10123, 10167, 10205, + 10237, 10263, 10283, 10295, 10301, 10302, 0, 1, 7, 21, + 41, 67, 99, 137, 181, 231, 287, 349, 417, 491, + 571, 655, 745, 841, 941, 1047, 1159, 1275, 1395, 1521, + 1651, 1785, 1923, 2065, 2211, 2361, 2513, 2669, 2829, 2991, + 3155, 3321, 3491, 3663, 3837, 4011, 4187, 4365, 4543, 4723, + 4903, 5083, 5263, 5443, 5623, 5803, 5981, 6159, 6335, 6509, + 6683, 6855, 7025, 7191, 7355, 7517, 7677, 7833, 7985, 8135, + 8281, 8423, 8561, 8695, 8825, 8951, 9071, 9187, 9299, 9405, + 9505, 9601, 9691, 9775, 9855, 9929, 9997, 10059, 10115, 10165, + 10209, 10247, 10279, 10305, 10325, 10339, 10345, 10346, 0, 1, + 7, 21, 41, 67, 99, 137, 181, 231, 287, 349, + 417, 491, 571, 655, 745, 841, 943, 1049, 1161, 1277, + 1397, 1523, 1653, 1787, 1925, 2067, 2213, 2363, 2517, 2673, + 2833, 2995, 3159, 3327, 3497, 3669, 3843, 4019, 4195, 4373, + 4551, 4731, 4911, 5091, 5271, 5451, 5631, 5811, 5989, 6167, + 6343, 6519, 6693, 6865, 7035, 7203, 7367, 7529, 7689, 7845, + 7999, 8149, 8295, 8437, 8575, 8709, 8839, 8965, 9085, 9201, + 9313, 9419, 9521, 9617, 9707, 9791, 9871, 9945, 10013, 10075, + 10131, 10181, 10225, 10263, 10295, 10321, 10341, 10355, 10361, 10362, + 0, 1, 7, 21, 41, 67, 99, 137, 181, 231, + 287, 349, 417, 491, 571, 657, 747, 843, 945, 1051, + 1163, 1279, 1399, 1525, 1655, 1789, 1927, 2069, 2215, 2365, + 2519, 2675, 2835, 2997, 3161, 3329, 3499, 3671, 3845, 4021, + 4197, 4375, 4553, 4733, 4913, 5093, 5273, 5453, 5633, 5813, + 5991, 6169, 6345, 6521, 6695, 6867, 7037, 7205, 7369, 7531, + 7691, 7847, 8001, 8151, 8297, 8439, 8577, 8711, 8841, 8967, + 9087, 9203, 9315, 9421, 9523, 9619, 9709, 9795, 9875, 9949, + 10017, 10079, 10135, 10185, 10229, 10267, 10299, 10325, 10345, 10359, + 10365, 10366 +}; + +const Word16 ivas_pca_offset_n2[IVAS_PCA_N1] = +{ + 0, 2, 6, 14, 24, 38, 56, 76, 100, 126, 156, 188, + 224, 262, 302, 346, 392, 442, 494, 548, 604, 664, 726, 790, + 856, 924, 994, 1066, 1140, 1216, 1294, 1374, 1454, 1536, 1620, 1704, + 1790, 1878, 1966, 2054, 2144, 2234, 2324, 2416, 2508, 2600, 2692, 2784, + 2876, 2968, 3058, 3148, 3238, 3326, 3414, 3502, 3588, 3672, 3756, 3838, + 3918, 3998, 4076, 4152, 4226, 4298, 4368, 4436, 4502, 4566, 4628, 4688, + 4744, 4798, 4850, 4900, 4946, 4990, 5030, 5068, 5104, 5136, 5166, 5192, + 5216, 5236, 5254, 5268, 5278, 5286, 5290 +}; + +const Word16 ph1_q_n2_tbl[IVAS_PCA_N1][2] = { /* ph1_q : Q13, n2 : Q0 */ + { 0, 1 }, + { 286, 3 }, + { 572, 7 }, + { 858, 9 }, + { 1144, 13 }, + { 1430, 17 }, + { 1716, 19 }, + { 2002, 23 }, + { 2288, 25 }, + { 2574, 29 }, + { 2860, 31 }, + { 3146, 35 }, + { 3431, 37 }, + { 3717, 39 }, + { 4003, 43 }, + { 4289, 45 }, + { 4575, 49 }, + { 4861, 51 }, + { 5147, 53 }, + { 5433, 55 }, + { 5719, 59 }, + { 6005, 61 }, + { 6291, 63 }, + { 6577, 65 }, + { 6863, 67 }, + { 7149, 69 }, + { 7435, 71 }, + { 7721, 73 }, + { 8007, 75 }, + { 8293, 77 }, + { 8579, 79 }, + { 8865, 79 }, + { 9151, 81 }, + { 9437, 83 }, + { 9722, 83 }, + { 10008, 85 }, + { 10294, 87 }, + { 10580, 87 }, + { 10866, 87 }, + { 11152, 89 }, + { 11438, 89 }, + { 11724, 89 }, + { 12010, 91 }, + { 12296, 91 }, + { 12582, 91 }, + { 12868, 91 }, + { 13154, 91 }, + { 13440, 91 }, + { 13726, 91 }, + { 14012, 89 }, + { 14298, 89 }, + { 14584, 89 }, + { 14870, 87 }, + { 15156, 87 }, + { 15442, 87 }, + { 15728, 85 }, + { 16013, 83 }, + { 16299, 83 }, + { 16585, 81 }, + { 16871, 79 }, + { 17157, 79 }, + { 17443, 77 }, + { 17729, 75 }, + { 18015, 73 }, + { 18301, 71 }, + { 18587, 69 }, + { 18873, 67 }, + { 19159, 65 }, + { 19445, 63 }, + { 19731, 61 }, + { 20017, 59 }, + { 20303, 55 }, + { 20589, 53 }, + { 20875, 51 }, + { 21161, 49 }, + { 21447, 45 }, + { 21733, 43 }, + { 22019, 39 }, + { 22304, 37 }, + { 22590, 35 }, + { 22876, 31 }, + { 23162, 29 }, + { 23448, 25 }, + { 23734, 23 }, + { 24020, 19 }, + { 24306, 17 }, + { 24592, 13 }, + { 24878, 9 }, + { 25164, 7 }, + { 25450, 3 }, + { 25736, 1 } +}; + + +/*----------------------------------------------------------------------------------* + * Parametric MC ROM tables + *----------------------------------------------------------------------------------*/ + +const Word16 param_mc_band_grouping_20[20 + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 23, 27, 33, 40, 52, 60 +}; + +const Word16 param_mc_coding_band_mapping_20[20] = +{ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const Word16 param_mc_bands_coded_20[4] = +{ + 10, 14, 18, 20 +}; + +const Word16 param_mc_band_grouping_14[14 + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 28, 40, 60 +}; + +const Word16 param_mc_coding_band_mapping_14[14] = +{ + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 +}; + +const Word16 param_mc_bands_coded_14[4] = +{ + 8, 11, 13, 14 +}; + +const Word16 param_mc_band_grouping_10[10 + 1] = +{ + 0, 1, 2, 3, 5, 7, 10, 14, 20, 40, 60 +}; + + +const Word16 param_mc_bands_coded_10[4] = +{ + 6, 8, 9, 10 +}; + +const Word16 param_mc_coding_band_mapping_10[10] = +{ + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 +}; + +const Word16 Param_MC_index[MAX_CICP_CHANNELS] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +}; + + +const Word32 ivas_param_mc_dmx_fac_CICP6_2tc_fx[12] = +{ + 2147483647,0,1518500224,1518500224,2147483647,0, /*Lt*/ + 0,2147483647,1518500224,1518500224,0,2147483647 /*Rt*/ +}; + +const Word32 ivas_param_mc_dmx_fac_CICP12_2tc_fx[16] = +{ + 2147483647,0,1518500224,1518500224,2147483647,0,2147483647,0, /*Lt*/ + 0,2147483647,1518500224,1518500224,0,2147483647,0,2147483647 /*Rt*/ +}; + +const Word32 ivas_param_mc_dmx_fac_CICP12_3tc_fx[24] = +{ + 2147483647,0,0,0,2147483647,0,2147483647,0, /*Lt*/ + 0,2147483647,0,0,0,2147483647,0,2147483647, /*Rt*/ + 0,0,2147483647,2147483647,0,0,0,0 /*Ct*/ +}; + +const Word32 ivas_param_mc_dmx_fac_CICP14_2tc_fx[16] = +{ + 2147483647,0,1518500224,1518500224,2147483647,0,2147483647,0, /*Lt*/ + 0,2147483647,1518500224,1518500224,0,2147483647,0,2147483647 /*Rt*/ +}; +const Word32 ivas_param_mc_dmx_fac_CICP14_3tc_fx[24] = +{ + 2147483647,0,0,0,2147483647,0,2147483647,0, /*Lt*/ + 0,2147483647,0,0,0,2147483647,0,2147483647, /*Rt*/ + 0,0,2147483647,2147483647,0,0,0,0 /*Ct*/ +}; + +const Word32 ivas_param_mc_dmx_fac_CICP16_3tc_fx[30] = +{ + 2147483647,0,0,0,2147483647,0,2147483647,0,2147483647,0, /*Lt*/ + 0,2147483647,0,0,0,2147483647,0,2147483647,0,2147483647, /*Rt*/ + 0,0,2147483647,2147483647,0,0,0,0,0,0 /*Ct*/ +}; + +const Word32 ivas_param_mc_dmx_fac_CICP19_3tc_fx[36] = +{ + 2147483647,0,0,0,2147483647,0,2147483647,0,2147483647,0,2147483647,0, /*Lt*/ + 0,2147483647,0,0,0,2147483647,0,2147483647,0,2147483647,0,2147483647, /*Rt*/ + 0,0,2147483647,2147483647,0,0,0,0,0,0,0,0 /*Ct*/ +}; + +const Word32 ivas_param_mc_dmx_fac_CICP19_4tc_fx[48] = +{ + 2147483647,0,1518500224,1518500224,2147483647,0,2147483647,0,0,0,0,0, /*Lht*/ + 0,2147483647,1518500224,1518500224,0,2147483647,0,2147483647,0,0,0,0, /*Rht*/ + 0,0,0,0,0,0,0,0,2147483647,0,2147483647,0, /*Lut*/ + 0,0,0,0,0,0,0,0,0,2147483647,0,2147483647 /*Rut*/ +}; + + +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP6_2tc_fx[6] = +{ + 12832, + 12832, + 6820, + 10607, + 10607, + 6820 +}; + +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP12_2tc_fx[8] = +{ + 11965, + 11965, + 6816, + 6877, + 6877, + 5619, + 5619, + 6816 +}; + +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP12_3tc_fx[8] = +{ + 16384, + 16384, + 9502, + 9502, + 6553, + 6553, + 32767, + 8192 +}; +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP14_2tc_fx[8] = +{ + 11936, + 11936, + 5993, + 6945, + 6945, + 8049, + 8049, + 6816 +}; + +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP14_3tc_fx[8] = +{ + 16291, + 16291, + 8257, + 8257, + 9666, + 9666, + 32767, + 8192 +}; + +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP16_3tc_fx[10] = +{ + 11141, + 11141, + 7209, + 7209, + 6553, + 6553, + 5898, + 5898, + 32767, + 8192 +}; + +//Q15 +const Word16 ivas_param_mc_ild_fac_CICP19_3tc_fx[12] = +{ + 9830, + 9830, + 5570, + 5570, + 3932, + 3932, + 6226, + 6226, + 6226, + 6226, + 32767, + 16384 +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP6_2tc = +{ + 5, + 6, + {0,1,2,4,5,3}, + {1,1,2,1,1,2}, + {{0},{1},{0,1},{0},{1},{0,1}} +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP12_2tc = +{ + 7, + 8, + {0,1,2,4,5,6,7,3}, + {1,1,2,1,1,1,1,2}, + {{0},{1},{0,1},{0},{1},{0},{1},{0,1}} +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP12_3tc = +{ + 6, + 8, + {0,1,4,5,6,7,2,3}, + {1,1,1,1,1,1,1,1}, + {{0},{1},{0},{1},{0},{1},{2},{2}} +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP14_2tc = +{ + 7, + 8, + {0,1,2,4,5,6,7,3}, + {1,1,2,1,1,1,1,2}, + {{0},{1},{0,1},{0},{1},{0},{1},{0,1}} +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP14_3tc = +{ + 6, + 8, + {0,1,4,5,6,7,2,3}, + {1,1,1,1,1,1,1,1}, + {{0},{1},{0},{1},{0},{1},{2},{2}} +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP16_3tc = +{ + 8, + 10, + {0,1,4,5,6,7,8,9,2,3}, + {1,1,1,1,1,1,1,1,1,1}, + {{0},{1},{0},{1},{0},{1},{0},{1},{2},{2}} +}; + +const PARAM_MC_ILD_MAPPING ivas_param_mc_ild_mapping_CICP19_3tc = +{ + 10, + 12, + {0,1,4,5,6,7,8,9,10,11,2,3}, + {1,1,1,1,1,1,1,1,1,1,1,1}, + {{0},{1},{0},{1},{0},{1},{0},{1},{0},{1},{2},{2}} +}; + +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP6_2tc = +{ + 4, + 5, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 2, 3 }} /* C/LFE */ +}; + +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP12_2tc = +{ + 6, + 7, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 2, 6 }, /* C/BLS */ + { 2, 7 }, /* C/BRS */ + { 2, 3 } /* C/LFE */ + } +}; + +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP12_3tc = +{ + 6, + 7, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 0, 6 }, /* L/BLS */ + { 1, 7 }, /* R/BRS */ + { 2, 3 } /* C/LFE */ + } +}; + +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP14_2tc = +{ + 6, + 7, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 2, 6 }, /* C/UFL */ + { 2, 7 }, /* C/UFR */ + { 2, 3 } /* C/LFE */ + } +}; +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP14_3tc = +{ + 6, + 7, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 0, 6 }, /* L/UFL */ + { 1, 7 }, /* R/UFR */ + { 2, 3 } /* C/LFE */ + } +}; + +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP16_3tc = +{ + 8, + 9, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 0, 6 }, /* L/UFL */ + { 1, 7 }, /* R/UFR */ + { 4, 8 }, /* LS/UBL */ + { 5, 9 }, /* RS/UBR */ + { 2, 3 } /* C/LFE */ + } +}; + +const PARAM_MC_ICC_MAPPING ivas_param_mc_icc_mapping_CICP19_3tc = +{ + 10, + 11, + { { 0, 4 }, /* L/LS */ + { 1, 5 }, /* R/RS */ + { 0, 2 }, /* L/C */ + { 1, 2 }, /* R/C */ + { 0, 6 }, /* L/LBS */ + { 1, 7 }, /* R/RBS */ + { 0, 8 }, /* L/UFL */ + { 1, 9 }, /* R/UFR */ + { 6, 10 }, /* LBS/UBL */ + { 7, 11 }, /* RBS/UBR */ + { 2, 3 } /* C/LFE */ + } +}; + +const PARAM_MC_CONF ivas_param_mc_conf[PARAM_MC_NUM_CONFIGS] = +{ + /* CICP6 48000 */ + { + MC_LS_SETUP_5_1, + 6, + 2, + IVAS_48k, + &ivas_param_mc_ild_mapping_CICP6_2tc, + &ivas_param_mc_icc_mapping_CICP6_2tc, + &ivas_param_mc_ild_fac_CICP6_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP6_2tc_fx[0] + }, + /* CICP6 64000 */ + { + MC_LS_SETUP_5_1, + 6, + 2, + IVAS_64k, + &ivas_param_mc_ild_mapping_CICP6_2tc, + &ivas_param_mc_icc_mapping_CICP6_2tc, + &ivas_param_mc_ild_fac_CICP6_2tc_fx[0], + & ivas_param_mc_dmx_fac_CICP6_2tc_fx[0] + }, + /* CICP6 80000 */ + { + MC_LS_SETUP_5_1, + 6, + 2, + IVAS_80k, + &ivas_param_mc_ild_mapping_CICP6_2tc, + &ivas_param_mc_icc_mapping_CICP6_2tc, + &ivas_param_mc_ild_fac_CICP6_2tc_fx[0], + & ivas_param_mc_dmx_fac_CICP6_2tc_fx[0] + }, + /* CICP12 48000 */ + { + MC_LS_SETUP_7_1, + 8, + 2, + IVAS_48k, + &ivas_param_mc_ild_mapping_CICP12_2tc, + &ivas_param_mc_icc_mapping_CICP12_2tc, + &ivas_param_mc_ild_fac_CICP12_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP12_2tc_fx[0] + }, + /* CICP12 64000 */ + { + MC_LS_SETUP_7_1, + 8, + 2, + IVAS_64k, + &ivas_param_mc_ild_mapping_CICP12_2tc, + &ivas_param_mc_icc_mapping_CICP12_2tc, + &ivas_param_mc_ild_fac_CICP12_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP12_2tc_fx[0] + }, + /* CICP12 80000 */ + { + MC_LS_SETUP_7_1, + 8, + 2, + IVAS_80k, + &ivas_param_mc_ild_mapping_CICP12_2tc, + &ivas_param_mc_icc_mapping_CICP12_2tc, + &ivas_param_mc_ild_fac_CICP12_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP12_2tc_fx[0], + }, + /* CICP12 96000 */ + { + MC_LS_SETUP_7_1, + 8, + 3, + IVAS_96k, + &ivas_param_mc_ild_mapping_CICP12_3tc, + &ivas_param_mc_icc_mapping_CICP12_3tc, + &ivas_param_mc_ild_fac_CICP12_3tc_fx[0], + &ivas_param_mc_dmx_fac_CICP12_3tc_fx[0] + }, + /* CICP14 48000 */ + { + MC_LS_SETUP_5_1_2, + 8, + 2, + IVAS_48k, + &ivas_param_mc_ild_mapping_CICP14_2tc, + &ivas_param_mc_icc_mapping_CICP14_2tc, + &ivas_param_mc_ild_fac_CICP14_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP14_2tc_fx[0] + }, + /* CICP14 64000 */ + { + MC_LS_SETUP_5_1_2, + 8, + 2, + IVAS_64k, + &ivas_param_mc_ild_mapping_CICP14_2tc, + &ivas_param_mc_icc_mapping_CICP14_2tc, + &ivas_param_mc_ild_fac_CICP14_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP14_2tc_fx[0] + }, + /* CICP14 80000 */ + { + MC_LS_SETUP_5_1_2, + 8, + 2, + IVAS_80k, + &ivas_param_mc_ild_mapping_CICP14_2tc, + &ivas_param_mc_icc_mapping_CICP14_2tc, + &ivas_param_mc_ild_fac_CICP14_2tc_fx[0], + &ivas_param_mc_dmx_fac_CICP14_2tc_fx[0] + }, + /* CICP14 96000 */ + { + MC_LS_SETUP_5_1_2, + 8, + 3, + IVAS_96k, + &ivas_param_mc_ild_mapping_CICP14_3tc, + &ivas_param_mc_icc_mapping_CICP14_3tc, + &ivas_param_mc_ild_fac_CICP14_3tc_fx[0], + &ivas_param_mc_dmx_fac_CICP14_3tc_fx[0] + }, + /* CICP16 96000 */ + { + MC_LS_SETUP_5_1_4, + 10, + 3, + IVAS_96k, + &ivas_param_mc_ild_mapping_CICP16_3tc, + &ivas_param_mc_icc_mapping_CICP16_3tc, + &ivas_param_mc_ild_fac_CICP16_3tc_fx[0], + &ivas_param_mc_dmx_fac_CICP16_3tc_fx[0] + }, + /* CICP16 128000 */ + { + MC_LS_SETUP_5_1_4, + 10, + 3, + IVAS_128k, + &ivas_param_mc_ild_mapping_CICP16_3tc, + &ivas_param_mc_icc_mapping_CICP16_3tc, + &ivas_param_mc_ild_fac_CICP16_3tc_fx[0], + &ivas_param_mc_dmx_fac_CICP16_3tc_fx[0] + }, + /* CICP19 128000 */ + { + MC_LS_SETUP_7_1_4, + 12, + 3, + IVAS_128k, + &ivas_param_mc_ild_mapping_CICP19_3tc, + &ivas_param_mc_icc_mapping_CICP19_3tc, + &ivas_param_mc_ild_fac_CICP19_3tc_fx[0], + &ivas_param_mc_dmx_fac_CICP19_3tc_fx[0] + } +}; + + +/* Alphabet for delta coding for the ICCs in Parametric MC processing */ +const UWord16 ivas_param_mc_cum_freq_icc_cicp6_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = +{ + 0, 24, 224, 20873, 42384, 51699, 57122, 60572, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_cicp6_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 24, 200, 20649, 21511, 9315, 5423, 3450, 4963 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 0, 4, 9, 124, 447, 1311, 4453, 18116, 48636, 60573, 63692, 64746, 65327, 65531, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1] = +{ + 4, 5, 115, 323, 864, 3142, 13663, 30520, 11937, 3119, 1054, 581, 204, 3, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_cicp12_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = +{ + 0, 30, 848, 26611, 47846, 57358, 61679, 63237, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_cicp12_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 30, 818, 25763, 21235, 9512, 4321, 1558, 2298 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 0, 2, 7, 53, 243, 979, 3994, 16732, 49642, 61343, 64331, 65158, 65438, 65532, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1] = +{ + 2, 5, 46, 190, 736, 3015, 12738, 32910, 11701, 2988, 827, 280, 94, 2, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_cicp14_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = +{ + 0, 46, 826, 27798, 49552, 58447, 62046, 63284, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_cicp14_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER ]={ + 46, 780, 26972, 21754, 8895, 3599, 1238, 2251 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_delta_cicp14_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 0, 3, 8, 36, 172, 763, 3436, 15845, 50168, 62005, 64676, 65298, 65481, 65533, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_delta_cicp14_48_16bits[2* PARAM_MC_SZ_ICC_QUANTIZER - 1] = +{ + 3, 5, 28, 136, 591, 2673, 12409, 34323, 11837, 2671, 622, 183, 52, 1, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_combined_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER + 1] = +{ + 0, 34, 552, 24717, 45819, 54772, 59054, 61166, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_combined_48_16bits[PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 34, 518, 24165, 21102, 8953, 4282, 2112, 4369 +}; + +const UWord16 ivas_param_mc_cum_freq_icc_delta_combined_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER] = +{ + 0, 3, 7, 74, 304, 1009, 3870, 16502, 49834, 61384, 64217, 65020, 65369, 65531, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_icc_delta_combined_48_16bits[2 * PARAM_MC_SZ_ICC_QUANTIZER - 1] = +{ + 3, 4, 67, 230, 705, 2861, 12632, 33332, 11550, 2833, 803, 349, 162, 3, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_cicp6_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS + 1] = +{ + 0, 1092, 5574, 8315, 10652, 13875, 19656, 27664, 36284, 47058, 56251, 62579, 65118, 65462, 65513, 65532, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_cicp6_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 1092, 4482, 2741, 2337, 3223, 5781, 8008, 8620, 10774, 9193, 6328, 2539, 344, 51, 19, 3 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 0, 1, 2, 3, 5, 38, 146, 352, 638, 997, 1559, 2323, 3570, 5859, 10556, 21075, 44682, 55617, 60408, 62739, 63833, 64443, 64809, 65074, 65279, 65400, 65484, 65531, 65532, 65533, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_delta_cicp6_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = +{ + 1, 1, 1, 2, 33, 108, 206, 286, 359, 562, 764, 1247, 2289, 4697, 10519, 23607, 10935, 4791, 2331, 1094, 610, 366, 265, 205, 121, 84, 47, 1, 1, 1, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_cicp12_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS + 1] = +{ + 0, 967, 6335, 9941, 12837, 16652, 22416, 29814, 38807, 48497, 57184, 62661, 64916, 65466, 65514, 65530, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_cicp12_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 967, 5368, 3606, 2896, 3815, 5764, 7398, 8993, 9690, 8687, 5477, 2255, 550, 48, 16, 5 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 0, 1, 2, 3, 5, 18, 61, 149, 320, 592, 1083, 1793, 2974, 5257, 10133, 21274, 44342, 55891, 60895, 63174, 64244, 64793, 65100, 65287, 65406, 65477, 65517, 65531, 65532, 65533, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_delta_cicp12_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = +{ + 1, 1, 1, 2, 13, 43, 88, 171, 272, 491, 710, 1181, 2283, 4876, 11141, 23068, 11549, 5004, 2279, 1070, 549, 307, 187, 119, 71, 40, 14, 1, 1, 1, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_cicp14_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS + 1] = +{ + 0, 229, 7068, 10910, 13856, 17467, 22629, 29174, 36906, 46558, 55579, 61802, 65222, 65505, 65527, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_cicp14_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 229, 6839, 3842, 2946, 3611, 5162, 6545, 7732, 9652, 9021, 6223, 3420, 283, 22, 7, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_delta_cicp14_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 0, 1, 2, 3, 4, 12, 56, 153, 278, 475, 856, 1430, 2489, 4723, 9580, 20685, 45423, 56274, 60948, 63097, 64128, 64679, 65002, 65208, 65348, 65445, 65517, 65531, 65532, 65533, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_delta_cicp14_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = +{ + 1, 1, 1, 1, 8, 44, 97, 125, 197, 381, 574, 1059, 2234, 4857, 11105, 24738, 10851, 4674, 2149, 1031, 551, 323, 206, 140, 97, 72, 14, 1, 1, 1, 1 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_combined_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS+1] = +{ + 0, 1453, 8326, 12221, 15164, 18764, 24177, 31297, 39520, 49154, 57135, 62460, 64821, 65468, 65514, 65530, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_combined_48_16bits[PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 1453, 6873, 3895, 2943, 3600, 5413, 7120, 8223, 9634, 7981, 5325, 2361, 647, 46, 16, 5 +}; + +const UWord16 ivas_param_mc_cum_freq_ild_delta_combined_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS] = +{ + 0, 1, 2, 3, 5, 29, 98, 220, 414, 699, 1186, 1876, 3049, 5304, 10013, 20612, 45247, 56109, 60818, 63022, 64081, 64647, 64977, 65198, 65348, 65443, 65502, 65530, 65532, 65533, 65534, 65535 +}; + +const UWord16 ivas_param_mc_sym_freq_ild_delta_combined_48_16bits[2 * PARAM_MC_SZ_ILD_QUANTIZER_4BITS - 1] = +{ + 1, 1, 1, 2, 24, 69, 122, 194, 285, 487, 690, 1173, 2255, 4709, 10599, 24635, 10862, 4709, 2204, 1059, 566, 330, 221, 150, 95, 59, 28, 2, 1, 1, 1 +}; + + +/*----------------------------------------------------------------------------------* + * MASA ROM tables + *----------------------------------------------------------------------------------*/ + +const Word64 diffuseness_reconstructions_hr_fx[HR_MASA_ER_LEVELS] = { /* Q62 */ + 0, + 65865144550293504, + 138485688541642752, + 239816680157478912, + 355502895585558528, + 485544334825881600, + 667940119734386688, + 902690250311073792, + 1225260573621485568, + 1635651089665622016, + 2011983133527769088, + 2354256705207926784, + 2741003323208368128, + 3172222987529093120, + 3693796119373938688, + 4305722718742904832, +}; + +const Word32 diffuseness_thresholds_hr_fx[HR_MASA_ER_LEVELS + 1] = { /* Q30 */ + 0, + 10223616, + 20447232, + 44040192, + 67633152, + 97910784, + 128188416, + 182845440, + 237502464, + 333053952, + 428605440, + 508297216, + 587988992, + 688390144, + 788791296, + 931266560, + MAX_32 /* out-of-range large value to make searching easier */ +}; + +const Word16 bits_direction_masa[DIRAC_DIFFUSE_LEVELS] = +{ + 11, + 11, + 10, + 9, + 7, + 6, + 5, + 3 +}; + + +const Word16 len_cb_dct0_masa[DIRAC_DIFFUSE_LEVELS] = { 7, 6, 5, 4, 4, 4, 3, 2 }; + +const UWord8 sur_coherence_cb_masa[MASA_MAX_NO_CV_SUR_COH*MASA_NO_CB_SUR_COH] = +{ + 16, 99, 0, 0, 0, 0, 0, 0, + 12, 64, 167, 0, 0, 0, 0, 0, + 10, 45, 100, 218, 0, 0, 0, 0, + 8, 34, 70, 124, 235, 0, 0, 0, + 7, 27, 55, 90, 141, 242, 0, 0, + 7, 23, 45, 71, 105, 153, 247, 0, + 6, 20, 38, 60, 86, 119, 165, 249 +}; + +const Word16 idx_cb_sur_coh_masa[MASA_MAX_NO_CV_SUR_COH] = { 0, 1, 2, 3, 4, 5, 5, 6 }; + +const Word16 len_huf_masa[MASA_NO_CV_COH1] = { 4, 2, 1, 3, 4 }; + +const Word16 huff_code_av_masa[MASA_NO_CV_COH1] = { 15, 2, 0, 6, 14 }; + +const Word16 no_theta_masa[NO_SPHERICAL_GRIDS-2] = /* from 1 to 11 bits */ +{ /*1, 1,*/ 2 ,2 , 4, 5, 6, 7, 10, 14, 19 + /*0, 2, 8, 6, 7, 12, 14, 16*/ +}; + +const Word16 no_phi_masa[NO_SPHERICAL_GRIDS][MAX_NO_THETA] = /* from 1 to 11 bits*/ +{ + { 2 }, + { 4 }, + { 4, 2 }, + { 8, 4 }, /* 8, 4*/ + { 12, 7, 2, 1 }, /* 12, */ + { 14, 13, 9, 2, 1 }, + { 22, 21, 17, 11, 3, 1 }, + { 33, 32, 29, 23, 17, 9, 1 }, + { 48, 47, 45, 41, 35, 28, 20, 12, 2, 1 }, + { 60, 60, 58, 56, 54, 50, 46, 41, 36, 30, 23, 17, 10, 1 }, + { 89, 89, 88, 86, 84, 81, 77, 73, 68, 63, 57, 51, 44, 38, 30, 23, 15, 8, 1 } +}; + +const Word16 MASA_band_grouping_24[24 + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30, 40, 60 +}; + +const Word16 MASA_band_mapping_24_to_18[18 + 1] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 17, 20, 21, 22, 23, 24 +}; + +const Word16 MASA_band_mapping_24_to_12[12 + 1] = +{ + 0, 1, 2, 3, 4, 5, 7, 9, 12, 15, 20, 22, 24 +}; + +const Word16 MASA_band_mapping_24_to_8[8 + 1] = +{ + 0, 1, 2, 3, 5, 8, 12, 20, 24 +}; + +const Word16 MASA_band_mapping_24_to_5[5 + 1] = +{ + 0, 1, 3, 7, 15, 24 +}; + +const Word16 MASA_grouping_8_to_5[8] = +{ + 0, 1, 1, 2, 3, 3, 4, 4 +}; + +const Word16 MASA_grouping_12_to_5[12] = +{ + 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4 +}; + +const Word16 MASA_grouping_18_to_5[18] = +{ + 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4 +}; + +const Word16 MASA_grouping_24_to_5[24] = +{ + 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 +}; + +/* IVAS_13k2, IVAS_16k4, IVAS_24k4, IVAS_32k, IVAS_48k, IVAS_64k, IVAS_80k, IVAS_96k, IVAS_128k, IVAS_160k, IVAS_192k, IVAS_256k, IVAS_384k, IVAS_512k */ +const Word16 masa_bits[IVAS_NUM_ACTIVE_BRATES] = +{ + 50, 60, 70, 85, 140, 180, 220, 256, 350, 432, 528, 832, 1024, MASA_MAX_BITS +}; + +const Word16 masa_bits_LR_stereo[4] = +{ + 50, 50, 60, 70 +}; + +const Word16 mcmasa_bits[IVAS_NUM_ACTIVE_BRATES] = +{ + 50, 70, 80, 120, 140, 160, 220, 256, 288, 432, 528, 832, 1024, MASA_MAX_BITS +}; + +const UWord8 masa_nbands[IVAS_NUM_ACTIVE_BRATES] = +{ + 5, 5, 5, 5, 5, 5, 5, 5, 8, 12, 18, 24, 24, 24 +}; + +const UWord8 masa_joined_nbands[IVAS_NUM_ACTIVE_BRATES] = +{ + 5, 5, 5, 8, 12, 12, 12, 18, 18, 18, 18, 24, 24, 24 +}; + +const UWord8 masa_twodir_bands[IVAS_NUM_ACTIVE_BRATES] = +{ + 0, 0, 0, 0, 0, 1, 1, 1, 3, 4, 6, 6, 9, 24 +}; + +const UWord8 masa_twodir_bands_joined[IVAS_NUM_ACTIVE_BRATES] = +{ + 0, 0, 0, 0, 0, 2, 2, 3, 4, 6, 8, 9, 12, MASA_MAXIMUM_TWO_DIR_BANDS +}; + + +/*----------------------------------------------------------------------------------* + * OMASA ROM tables + *----------------------------------------------------------------------------------*/ + +const Word32 sep_object_brate[][MAX_NUM_OBJECTS] = +{ + {0, 0, 0, 0}, /* 13k2 */ + {0, 0, 0, 0}, /* 16k4 */ + {9600, 0, 0, 0}, /* 24k4 */ + {IVAS_13k2, 0, 0, 0}, /* 32k */ + {16000, 11000, 0, 0}, /* 48k */ + {16000, 11700, 0, 0}, /* 64k */ + {20000, 16000, 0, 0}, /* 80k */ + {IVAS_32k, 20000, 20000, 0}, /* 96k */ + {IVAS_32k, IVAS_24k4, 24000, 24000}, /* 128k */ + {IVAS_48k, IVAS_32k, IVAS_24k4, 24000}, /* 160k */ + {IVAS_64k, IVAS_48k, IVAS_32k, IVAS_24k4}, /* 192k */ + {IVAS_96k, IVAS_64k, IVAS_48k, IVAS_32k}, /* 256k */ + {IVAS_128k, IVAS_80k, IVAS_64k, IVAS_48k}, /* 384k */ + {IVAS_128k, IVAS_96k, IVAS_80k, IVAS_64k} /* 512k */ +}; + +/* column wise DCT matrices for 4 5, and 8 dim */ +/*----------------------------------------------------------------------------------* + * Param ISM ROM tables + *----------------------------------------------------------------------------------*/ + +const Word16 Param_ISM_band_grouping[MAX_PARAM_ISM_NBANDS + 1] = +{ + 0, 1, 2, 3, 4, 6, 8, 11, 15, 21, 31, 60 +}; + +/*----------------------------------------------------------------------------------* + * LFE coding ROM tables + *----------------------------------------------------------------------------------*/ + +const ivas_lfe_freq_models ivas_str_lfe_freq_models = +{ + { 16384, 14924, 13463, 12003, 10542, 9082, 7622, 6161, + 4701, 4336, 3970, 3605, 3240, 2875, 2510, 2145, + 1780, 1689, 1597, 1506, 1415, 1323, 1232, 1141, + 1050, 1004, 958, 913, 867, 821, 776, 730, + 685, 639, 593, 548, 502, 456, 411, 365, + 319, 297, 274, 251, 228, 205, 183, 160, + 137, 126, 114, 103, 91, 80, 68, 57, + 46, 40, 34, 29, 23, 17, 11, 6, 0 }, + + { 16384, 13463, 10542, 7622, 4701, 3970, 3240, 2510, + 1780, 1597, 1415, 1232, 1050, 958, 867, 776, + 685, 593, 502, 411, 319, 274, 228, 183, + 137, 114, 91, 68, 46, 34, 23, 11, 0 }, + + { 16384, 4701, 1780, 1050, 685, 319, 137, 46, + 0, }, + + { 16384, 3277, 0 }, + + { 16384, 13463, 10542, 7622, 4701, 3970, 3240, 2510, + 1780, 1597, 1415, 1232, 1050, 958, 867, 776, + 685, 593, 502, 411, 319, 274, 228, 183, + 137, 114, 91, 68, 46, 34, 23, 11, + 0 }, + + { 16384, 10542, 4701, 3240, 1780, 1415, 1050, 867, + 685, 502, 319, 228, 137, 91, 46, 23, + 0 }, + + { 16384, 4468, 1489, 745, 0 }, 0, +}; + +const Word16 ivas_lfe_num_ele_in_coder_models[2][4] = +{ + { 63, 31, 7, 1 },{ 31, 15, 3, 0 } +}; + +const Word16 ivas_lfe_log2_num_ele_in_coder_models_fx[2][4] = +{ + { 6, 5, 3, 1 },{ 5, 4, 2, 0 } +}; + +const Word16 ivas_lfe_num_dct_pass_bins_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 8, 6 }; + +const Word16 ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 1, 0 }; + +const Word16 ivas_lfe_lpf_delay_Q15[2] = { 57, 114 }; + +const Word16 dirac_gains_P_idx[16] = +{ + -1, 1, 0, 1, 4, 3, 2, 3, 4, 8, 7, 6, 5, 6, 7, 8 +}; + +/*----------------------------------------------------------------------------------* + * FB ROM tables + *----------------------------------------------------------------------------------*/ + +const Word32 ivas_fb_fcs_12band_1ms_fx[IVAS_FB_BANDS_12] = +{ + 17895696, 53687092, 89478488, 125269880, + 161061280, 196852672, 232644064, 304226848, + 465288128, 715827904, 1091637520, 1735882615 +};/*Q31*/ + +const Word16 ivas_fb_abs_bins_per_band_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = +{ + { 24, 30, 30, 30, 30, 30, 42, 76, 124, 182, 291, 367 }, + { 24, 30, 30, 30, 30, 30, 42, 76, 124, 182, 260, 47 }, + { 24, 30, 30, 30, 30, 30, 42, 75, 122, 73, 0, 0 } +}; + +const Word16 ivas_fb_abs_bins_start_offset_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = +{ + {0, 9, 25, 41, 57, 73, 88, 110, 158, 246, 380, 593 }, + {0, 9, 25, 41, 57, 73, 88, 110, 158, 246, 380, 593 }, + {0, 9, 25, 41, 57, 73, 88, 110, 159, 247, 0, 0 } +}; + +const Word16 ivas_fb_bins_per_band_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = +{ + { + IVAS_FB_12_1MS_48K_END_BINS_BAND_0 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_0, + IVAS_FB_12_1MS_48K_END_BINS_BAND_1 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_1, + IVAS_FB_12_1MS_48K_END_BINS_BAND_2 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_2, + IVAS_FB_12_1MS_48K_END_BINS_BAND_3 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_3, + IVAS_FB_12_1MS_48K_END_BINS_BAND_4 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_4, + IVAS_FB_12_1MS_48K_END_BINS_BAND_5 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_5, + IVAS_FB_12_1MS_48K_END_BINS_BAND_6 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_6, + IVAS_FB_12_1MS_48K_END_BINS_BAND_7 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_7, + IVAS_FB_12_1MS_48K_END_BINS_BAND_8 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_8, + IVAS_FB_12_1MS_48K_END_BINS_BAND_9 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_9, + IVAS_FB_12_1MS_48K_END_BINS_BAND_10 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_10, + IVAS_FB_12_1MS_48K_END_BINS_BAND_11 - IVAS_FB_12_1MS_48K_START_OFFSET_BAND_11 + }, + { + IVAS_FB_12_1MS_32K_END_BINS_BAND_0 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_0, + IVAS_FB_12_1MS_32K_END_BINS_BAND_1 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_1, + IVAS_FB_12_1MS_32K_END_BINS_BAND_2 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_2, + IVAS_FB_12_1MS_32K_END_BINS_BAND_3 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_3, + IVAS_FB_12_1MS_32K_END_BINS_BAND_4 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_4, + IVAS_FB_12_1MS_32K_END_BINS_BAND_5 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_5, + IVAS_FB_12_1MS_32K_END_BINS_BAND_6 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_6, + IVAS_FB_12_1MS_32K_END_BINS_BAND_7 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_7, + IVAS_FB_12_1MS_32K_END_BINS_BAND_8 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_8, + IVAS_FB_12_1MS_32K_END_BINS_BAND_9 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_9, + IVAS_FB_12_1MS_32K_END_BINS_BAND_10 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_10, + IVAS_FB_12_1MS_32K_END_BINS_BAND_11 - IVAS_FB_12_1MS_32K_START_OFFSET_BAND_11 + }, + { + IVAS_FB_12_1MS_16K_END_BINS_BAND_0 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_0, + IVAS_FB_12_1MS_16K_END_BINS_BAND_1 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_1, + IVAS_FB_12_1MS_16K_END_BINS_BAND_2 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_2, + IVAS_FB_12_1MS_16K_END_BINS_BAND_3 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_3, + IVAS_FB_12_1MS_16K_END_BINS_BAND_4 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_4, + IVAS_FB_12_1MS_16K_END_BINS_BAND_5 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_5, + IVAS_FB_12_1MS_16K_END_BINS_BAND_6 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_6, + IVAS_FB_12_1MS_16K_END_BINS_BAND_7 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_7, + IVAS_FB_12_1MS_16K_END_BINS_BAND_8 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_8, + IVAS_FB_12_1MS_16K_END_BINS_BAND_9 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_9, + IVAS_FB_12_1MS_16K_END_BINS_BAND_10 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_10, + IVAS_FB_12_1MS_16K_END_BINS_BAND_11 - IVAS_FB_12_1MS_16K_START_OFFSET_BAND_11 + }, +}; + +const Word16 ivas_fb_bins_start_offset_12band_1ms[IVAS_NUM_SUPPORTED_FS][IVAS_FB_BANDS_12] = +{ + { + IVAS_FB_12_1MS_48K_START_OFFSET_BAND_0, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_1, + IVAS_FB_12_1MS_48K_START_OFFSET_BAND_2, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_3, + IVAS_FB_12_1MS_48K_START_OFFSET_BAND_4, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_5, + IVAS_FB_12_1MS_48K_START_OFFSET_BAND_6, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_7, + IVAS_FB_12_1MS_48K_START_OFFSET_BAND_8, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_9, + IVAS_FB_12_1MS_48K_START_OFFSET_BAND_10, IVAS_FB_12_1MS_48K_START_OFFSET_BAND_11 + }, + { + IVAS_FB_12_1MS_32K_START_OFFSET_BAND_0, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_1, + IVAS_FB_12_1MS_32K_START_OFFSET_BAND_2, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_3, + IVAS_FB_12_1MS_32K_START_OFFSET_BAND_4, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_5, + IVAS_FB_12_1MS_32K_START_OFFSET_BAND_6, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_7, + IVAS_FB_12_1MS_32K_START_OFFSET_BAND_8, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_9, + IVAS_FB_12_1MS_32K_START_OFFSET_BAND_10, IVAS_FB_12_1MS_32K_START_OFFSET_BAND_11 + }, + { + IVAS_FB_12_1MS_16K_START_OFFSET_BAND_0, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_1, + IVAS_FB_12_1MS_16K_START_OFFSET_BAND_2, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_3, + IVAS_FB_12_1MS_16K_START_OFFSET_BAND_4, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_5, + IVAS_FB_12_1MS_16K_START_OFFSET_BAND_6, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_7, + IVAS_FB_12_1MS_16K_START_OFFSET_BAND_8, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_9, + IVAS_FB_12_1MS_16K_START_OFFSET_BAND_10, IVAS_FB_12_1MS_16K_START_OFFSET_BAND_11 + }, +}; + + +const Word16 ivas_num_active_bands[FB - WB + 1] = +{ + IVAS_16K_12BANDS_ACTIVE_BANDS, IVAS_FB_BANDS_12, IVAS_FB_BANDS_12 +}; + +/*------------------------------------------------------------------------------------------* + * SNS MSVQ codebooks and means + *------------------------------------------------------------------------------------------*/ + +const Word16 ivas_sns_cdbks_tcx20_levels[SNS_MSVQ_NSTAGES_TCX20] = { 128, 64, 32, 32 }; + +const Word16 ivas_sns_cdbks_tcx20_bits[SNS_MSVQ_NSTAGES_TCX20] = { 7, 6, 5, 5 }; + +/* pre-rounded codebook vectors for singed Q4.12 represantation */ + +const Word16 ivas_sns_cdbks_tcx10_levels[SNS_MSVQ_NSTAGES_TCX10] = { 128, 32, 8 }; + +const Word16 ivas_sns_cdbks_tcx10_bits[SNS_MSVQ_NSTAGES_TCX10] = { 7, 5, 3 }; + + +const Word16 ivas_sns_cdbks_side_tcx20_levels[SNS_MSVQ_NSTAGES_SIDE] = { 32, 32 }; +const Word16 ivas_sns_cdbks_side_tcx20_bits[SNS_MSVQ_NSTAGES_SIDE] = { 5, 5 }; +const Word16 ivas_sns_cdbks_side_tcx10_levels[SNS_MSVQ_NSTAGES_SIDE] = { 32, 8 }; +const Word16 ivas_sns_cdbks_side_tcx10_bits[SNS_MSVQ_NSTAGES_SIDE] = { 5, 3 }; + + +const Word16 sns_1st_cdbk[2][2][8 * 32] = +{ + { /* split 1 */ + { /* TCX 20 */ + -10900, -11064, -10637, -10471, -9051, -6381, -4688, -2438, + -2119, -5087, -6702, -8118, -7586, -6343, -4828, -3406, + 2004, -3443, -4289, -3757, -3234, -2952, -2313, -1781, + 1749, 5598, 3916, 732, -1472, -2964, -3275, -2332, + -11978, -14369, -5600, -545, 981, -929, -57, 1903, + 1745, 391, 202, 115, 256, -291, -862, -1637, + -4052, 2059, 4709, 6768, 5595, 1975, -1723, -1218, + 2093, 7263, 8679, 7576, 3701, -2438, -4389, -2686, + -7120, -6279, -5715, -5520, -4752, -3125, -1856, -438, + 8131, -2543, -6285, -6723, -5588, -4321, -3264, -2164, + -653, -1301, -660, 608, 1598, 1805, 1698, 760, + 4882, 9309, 6333, 1734, 284, 364, 560, 1015, + -7686, -5737, -3443, -1642, 245, 1531, 1827, 1769, + -1468, 3782, 144, -5130, -6883, -5165, -1497, 2072, + -12937, -8429, -2619, 2894, 5004, 4710, 4627, 3740, + 3198, 3928, 4358, 4554, 3887, 2844, 1299, 129, + -13828, -12296, -9364, -7918, -5571, -1909, 307, 2047, + -4314, -1211, -559, -1061, -1928, -2228, -2359, -1902, + -309, -3224, -3404, -1895, -743, -59, 757, 908, + 10914, 5865, 1599, -386, -1392, -2285, -2236, -2042, + -11825, -16241, -11402, -3627, 6556, 8953, 6421, 1546, + 6102, 777, -301, 536, 902, 541, 210, -429, + -3052, 3997, 5389, 1842, -344, 1556, 2667, 2428, + 11788, 10894, 7448, 5423, 2372, -677, -2385, -3839, + -45, -7602, -8923, -7179, -3273, 65, 4500, 6726, + 5895, 626, -1610, -2598, -3240, -3540, -2930, -2156, + -971, 461, 1494, 4907, 5859, 5199, 3678, 2502, + 10766, 5297, 1844, 1236, 2498, 3503, 2846, 838, + -7816, -1212, 891, 2387, 1317, 2225, 1859, 1602, + 2376, 5357, 2088, -2719, -3419, -420, 2431, 2943, + -8383, -795, 4351, 7026, 7460, 7191, 5262, 3796, + 1522, 6283, 8714, 8222, 7434, 5768, 3586, 1499, + }, + { /* TCX 10 */ + -15596, -16321, -10264, -1002, 5955, 5543, -29, -1688, + 17, -3794, -6207, -7356, -6998, -6081, -4453, -2448, + -12543, -11530, -10186, -8817, -7083, -4440, -1946, 892, + 5198, 2751, -274, -2574, -4561, -6087, -5944, -4600, + -683, -2640, -2753, -1195, -239, -217, -286, 90, + -1400, -1146, -1853, -2845, -3456, -3788, -3171, -1969, + -1835, 392, 1725, 1209, -392, -1640, -2001, -1608, + 5770, 7707, 5210, 2112, -382, -2088, -2634, -3007, + -10766, -8101, -5137, -3754, -1881, 331, 2339, 3679, + -2637, -4640, -5811, -5651, -3790, -1359, 913, 1893, + -7793, -4768, -1762, -545, -717, -837, -441, -75, + 4030, 1770, 467, 379, 10, -1330, -2398, -2290, + -9395, -6952, -2494, 2022, 4753, 5614, 4443, 2642, + -1486, 1748, 859, -2586, -3368, -638, 2761, 3269, + -2408, 306, 3633, 6567, 5950, 2474, -621, -1421, + 5478, 7986, 9498, 8165, 5477, 1244, -523, -1586, + -13564, -14673, -10597, -5504, 1575, 8248, 7662, 4025, + 4978, -682, -3586, -4305, -3703, -3001, -2227, -1278, + -8002, -6831, -5558, -4868, -4243, -3393, -2486, -1110, + 11485, 5472, 1645, -533, -1792, -2814, -3169, -2706, + 1617, 421, 232, 1382, 2162, 2017, 1318, 744, + 3677, 5212, 1990, -1514, -2894, -2441, -451, 592, + 731, 4295, 5860, 3756, 1991, 1437, 869, 127, + 12736, 11722, 7768, 4682, 1574, -744, -1989, -3131, + -3490, -4269, -3681, -1531, 1111, 3327, 4138, 3815, + 7344, 1400, -1302, -1502, -1015, 57, 1212, 1498, + -4836, -1881, 1071, 2055, 2114, 2465, 2093, 1458, + 8569, 5879, 3654, 2879, 2530, 1703, 781, -233, + -3709, -990, 2338, 6227, 7083, 7102, 5657, 3401, + 3389, 6392, 5267, 1011, 275, 3519, 5236, 4339, + 599, 3752, 6943, 9211, 8152, 5568, 3337, 1838, + 9885, 9591, 7905, 8068, 7929, 7421, 4234, 757, + } + }, + { /* split 2 */ + { /* TCX 20 */ + -178, -3476, -5982, -7081, -7548, -7440, -6859, -5798, + -3596, -3670, -1501, 770, 812, -286, -2001, -3377, + -3998, -5191, -4988, -4421, -3889, -3571, -2738, -1969, + -2981, -2687, -1501, -83, 1136, 2377, 3248, 4105, + 1842, -41, -1972, -4282, -6779, -8405, -8674, -7835, + -259, 571, 2124, 3344, 2959, 1407, -750, -2523, + -524, -1956, -2855, -3202, -3939, -4666, -4907, -4782, + -5110, -4768, -3017, -663, 4188, 9210, 16602, 21081, + 4373, 4846, -603, -6495, -7289, -5540, -4749, -5527, + -1448, -1043, -619, -105, 356, 362, 542, 857, + 1373, -752, -5334, -6244, -3001, -932, -1040, -3125, + -2403, -1397, 612, 2449, 3920, 5231, 6819, 8581, + 2183, 1211, -111, -1084, -2836, -4977, -6701, -7284, + -751, 1255, 3408, 6474, 7503, 7026, 5413, 4464, + 935, 850, 589, 353, 160, -434, -939, -931, + 268, 2284, 3884, 5423, 6680, 7996, 9244, 9472, + 1075, 113, -1289, -4457, -7512, -5930, -1799, -571, + -3689, -4254, -3755, -2995, -1581, -135, 1049, 1589, + -1166, -1752, -1790, -1897, -1927, -1831, -1359, -805, + -1494, -735, 635, 1993, 2909, 3546, 4226, 4956, + 4435, 4299, 4269, 1328, -3731, -7621, -9319, -9170, + 1358, 2227, 3873, 4469, 4692, 4057, 2601, 1608, + 813, 398, -499, -666, -1286, -2271, -3316, -4025, + -3300, -1255, 2181, 6431, 10002, 12760, 13549, 12584, + 3714, 4180, 484, -2905, -2864, -1359, -1256, -2477, + 308, 868, 1373, 1629, 1793, 1834, 1814, 1746, + 1472, 798, -282, -1935, -1818, 320, 2221, 2914, + 2281, 3240, 2988, 1400, 2383, 4072, 5667, 6675, + 2672, 2678, 2874, 2096, -226, -2301, -3861, -4534, + 4988, 7231, 7641, 7731, 7061, 6447, 5411, 3513, + 3978, 4156, 4126, 2896, 1469, 759, 368, -68, + -264, 4210, 8534, 11008, 11606, 11888, 11072, 8949, }, + { /* TCX 10 */ + -2852, -6158, -7231, -7830, -8012, -7922, -7556, -6706, + -3911, -5340, -5053, -4741, -4805, -4484, -3727, -3037, + -966, -1461, -1694, -2427, -3081, -3037, -2547, -2230, + -3455, -3315, -2451, -836, 1383, 3196, 3720, 3379, + 3052, 281, -3351, -6866, -9051, -9586, -8983, -8236, + -748, -4465, -4314, -2251, 29, -40, -3963, -6195, + 200, 1293, 2535, 2803, 1603, -186, -1397, -1697, + -1707, -265, 2196, 5295, 5894, 4216, 3440, 3826, + -237, -2133, -2279, -3149, -4377, -5638, -6520, -6764, + -2407, -2049, -1246, -664, -521, -430, -349, -211, + 3874, 1335, -1501, -2055, -1268, -990, -1852, -2871, + -1883, -1845, -1681, -484, 384, 2035, 5839, 9597, + 275, 380, 1048, 424, -1146, -3012, -4431, -5104, + -1699, -484, 756, 1261, 1279, 1377, 1975, 2590, + 2139, 4502, 3645, 4975, 6491, 5972, 5012, 4346, + -3821, -2581, -433, 2667, 6436, 10038, 11311, 8783, + 2359, -2689, -6604, -7039, -5992, -4268, -3711, -4840, + -2776, -4251, -4539, -3672, -2494, -1055, 280, 695, + 491, 866, 822, -44, -1009, -1165, -831, -538, + -1024, 91, 786, 1295, 2433, 3910, 4975, 5403, + 3117, 2590, 2337, -667, -4580, -8147, -9400, -9523, + -103, -630, -831, 669, 3062, 3398, 549, -1690, + 2113, 3467, 4279, 5047, 5344, 3361, 127, -2313, + -1199, 1153, 2914, 3688, 4260, 5421, 7471, 8831, + 2815, 2184, 316, -3058, -5596, -5564, -4343, -3793, + 922, 126, -1414, -1731, -1007, 359, 2029, 3088, + 4889, 4619, 2537, 1114, 950, 946, 799, 419, + -4271, -3750, -3359, -484, 1448, 4106, 10487, 20479, + 3818, 4687, 4064, 2212, -172, -2287, -3535, -4041, + 884, 2456, 3394, 2925, 2182, 2323, 2583, 2507, + 4767, 8057, 8263, 6461, 5003, 4055, 2923, 1845, + 19, 3813, 6926, 8432, 10141, 10850, 9692, 8383, + } + } +}; + +const Word16 sns_1st_means_16k[2][16] = +{ + { /* TCX 20 */ + 14210, 19017, 14362, 9309, 5385, 2674, 1055, -211, -1407, -3059, -4393, -8597, -11180, -11756, -12131, -13281, + }, + { /* TCX 10*/ + 12018, 15915, 11089, 6015, 847, -705, -539, -1548, -893, -2163, -1806, -4189, -7017, -8670, -8874, -9480, + } +}; + +const Word16 sns_1st_means_25k6[2][16] = +{ + { /* TCX 20 */ + 14973, 20323, 16461, 9554, 4017, 3103, 1602, 1694, -221, -1401, -6817, -10071, -11503, -11805, -13158, -16749, + }, + { /* TCX 10 */ + 15560, 19489, 14623, 5595, 2084, 1699, 775, -1312, -2195, -6101, -9078, -9465, -7825, -6603, -7281, -9960, + } +}; + +const Word16 sns_1st_means_32k[2][16] = +{ + { /* TCX 20 */ + 15041, 20603, 16969, 10289, 4973, 4283, 3003, 3316, 1684, -259, -6614, -9535, -10363, -11834, -16625, -24930, + }, + { /* TCX 10 */ + 16510, 20660, 16025, 7224, 3921, 3868, 2623, 742, -1316, -6269, -8284, -7288, -6380, -8410, -13351, -20277, + } +}; + +/*----------------------------------------------------------------------* + * MC ParamUpmix ROM tables + *-----------------------------------------------------------------------*/ + +const Word16 ivas_param_upmx_mx_qmap[33] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0 +}; - }; \ No newline at end of file diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 60bdda941..94ad05426 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -654,25 +654,27 @@ static ivas_error ivas_alloc_pppMem_fx( return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" ); } - FOR( i = 0; i < dim1; i++ ){ - IF( ( localMem[i] = (Word32 **) malloc( dim2 * sizeof( Word32 * ) ) ) == NULL ){ - return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" ); -} -IF( allocate_init_flag == 0 ) -{ - FOR( j = 0; j < dim2; j++ ) + for ( i = 0; i < dim1; i++ ) { - IF( ( localMem[i][j] = (Word32 *) malloc( dim3 * sizeof( Word32 ) ) ) == NULL ) + IF( ( localMem[i] = (Word32 **) malloc( dim2 * sizeof( Word32 * ) ) ) == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" ); } + IF( allocate_init_flag == 0 ) + { + FOR( j = 0; j < dim2; j++ ) + { + IF( ( localMem[i][j] = (Word32 *) malloc( dim3 * sizeof( Word32 ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HRTF memory" ); + } + } + } } -} -} -*pppMem = localMem; + *pppMem = localMem; -return IVAS_ERR_OK; + return IVAS_ERR_OK; } /*-------------------------------------------------------------------------* -- GitLab From dfc596d78345cbe2b391c3be4f3ca5eac1ac7e6f Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 13:18:35 +1100 Subject: [PATCH 12/43] linux compilation fix --- lib_com/ivas_rom_com.c | 5 +++-- lib_com/ivas_rotation_com.c | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c index 5df975cf8..9f2f244df 100644 --- a/lib_com/ivas_rom_com.c +++ b/lib_com/ivas_rom_com.c @@ -56,7 +56,7 @@ const Word32 ivas_brate_tbl[SIZE_IVAS_BRATE_TBL] = * IVAS limiter table *----------------------------------------------------------------------------------*/ const Word32 release_cnst_table[4][201] = // Q31 - { +{ { 1913946752, 1919716352, @@ -871,7 +871,7 @@ const Word32 release_cnst_table[4][201] = // Q31 }, - }; +}; /*------------------------------------------------------------------------- * DFT Stereo ROM tables @@ -3722,3 +3722,4 @@ const Word16 ivas_param_upmx_mx_qmap[33] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; +/* clang-format on */ diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index 8aae50841..1ed1a7244 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -38,6 +38,7 @@ #include "cnst.h" #include "prot.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #ifdef DEBUGGING #include "debug.h" #endif -- GitLab From 1f3d8a7b0de3300616884d62e7e06b2081c32675 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 13:24:13 +1100 Subject: [PATCH 13/43] clang formatting fix --- lib_dec/ivas_binRenderer_internal.c | 2 +- lib_dec/ivas_objectRenderer_internal.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 94ad05426..c31f0cbf7 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -2164,4 +2164,4 @@ void ivas_rend_CldfbMultiBinRendProcess( return; } -#endif \ No newline at end of file +#endif diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 4e568b5ab..8a73539be 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -492,4 +492,4 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( return IVAS_ERR_OK; } -#endif \ No newline at end of file +#endif -- GitLab From 225019b3520b3bafce551e146dae1f0a410d131f Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 15:04:23 +1100 Subject: [PATCH 14/43] linux compilation fixes --- lib_com/ivas_prot_fx.h | 4 ++-- lib_com/ivas_rotation_com.c | 4 ++-- lib_dec/lib_dec.h | 2 +- lib_lc3plus/defines.h | 2 ++ lib_lc3plus/lc3.c | 2 ++ 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 8e0bfece9..88e8ed7ac 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -5961,8 +5961,8 @@ void modify_Quat_q_fx( ); void modify_Rmat_q_fx( - const Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ - Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ + Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ + Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ Word16 num_subframes, Word16 q_cur, /* i : current q factor for rotation matrix */ Word16 q_new /* i : target q factor for rotation matrix */ diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index 1ed1a7244..fccc5498b 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -130,8 +130,8 @@ void modify_Quat_q_fx( * Rotation matrix q factor modification *------------------------------------------------------------------------*/ void modify_Rmat_q_fx( - const Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ - Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ + Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ + Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ Word16 num_subframes, Word16 q_cur, /* i : current q factor for rotation matrix */ Word16 q_new /* i : target q factor for rotation matrix */ diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 0b20e64f9..dd2f14f09 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -147,7 +147,7 @@ ivas_error IVAS_DEC_GetSamples( #ifdef SPLIT_REND_WITH_HEAD_ROT ivas_error IVAS_DEC_GetSplitBinauralBitstream( IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - void *pcmBuf_out, /* o : output synthesis signal for BINAURAL_SPLIT_PCM */ + Word16 *pcmBuf_out, /* o : output synthesis signal for BINAURAL_SPLIT_PCM */ ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits */ Word16 *nOutSamples, /* o : number of samples per channel written to output buffer */ bool *needNewFrame /* o : indication that the decoder needs a new frame */ diff --git a/lib_lc3plus/defines.h b/lib_lc3plus/defines.h index f468568a9..ebf538b71 100644 --- a/lib_lc3plus/defines.h +++ b/lib_lc3plus/defines.h @@ -757,4 +757,6 @@ extern int fix_empty_translation_unit_warning; #define get_size_mpvq_calc_offset_fx get_size_mpvq_calc_offset_fx_lc3plus #endif +#define FIX_IVAS_LC3PLUS_WARNINGS + #endif diff --git a/lib_lc3plus/lc3.c b/lib_lc3plus/lc3.c index 120dd0929..68dd8a0bb 100644 --- a/lib_lc3plus/lc3.c +++ b/lib_lc3plus/lc3.c @@ -17,6 +17,7 @@ if (cond) \ return (error) +#ifndef FIX_IVAS_LC3PLUS_WARNINGS #ifdef SUBSET_NB #pragma message("- SUBSET_NB") #endif @@ -35,6 +36,7 @@ #ifdef SUBSET_UB #pragma message("- SUBSET_UB") #endif +#endif /* ensure api header constants are up to date */ STATIC_ASSERT(LC3PLUS_MAX_SAMPLES >= MAX_LEN); -- GitLab From d38113cbedfff1f2773abf9294d21f2d8f60c970 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 15:37:10 +1100 Subject: [PATCH 15/43] linux warning fixes --- apps/renderer.c | 3 --- lib_isar/isar_splitRend_lcld_dec.c | 2 +- lib_rend/lib_rend.c | 18 ++++++------------ 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index a41b633e2..6f55853d6 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -436,9 +436,6 @@ static void printSupportedAudioConfigs( void ); static IVAS_AUDIO_CONFIG parseAudioConfig( const char *configString ); #ifdef SPLIT_REND_WITH_HEAD_ROT -static void convertInputBuffer( const int16_t *intBuffer, const int16_t numIntSamplesPerChannel, const int16_t numFloatSamplesPerChannel, const int16_t numChannels, float *floatBuffer, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbAna ); - -static void convertOutputBuffer( const float *floatBuffer, const int16_t numSamplesPerChannel, const int16_t numChannels, int16_t *intBuffer, const int16_t cldfb_in, IVAS_CLDFB_FILTER_BANK_HANDLE *cldfbSyn ); static void convertOutputBuffer_fx( const Word32 *Word32Buffer, const Word16 numSamplesPerChannel, diff --git a/lib_isar/isar_splitRend_lcld_dec.c b/lib_isar/isar_splitRend_lcld_dec.c index 0d5ccae2f..98ca3d3ad 100644 --- a/lib_isar/isar_splitRend_lcld_dec.c +++ b/lib_isar/isar_splitRend_lcld_dec.c @@ -37,7 +37,7 @@ #include "ivas_prot.h" #include "prot.h" #include "prot_fx.h" -#include "control.h" +//#include "control.h" #ifdef DEBUGGING #include "debug.h" #endif diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 9b96ac146..bacdec5d1 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6250,7 +6250,6 @@ static ivas_error renderIsmToSplitBinaural( { ivas_error error; Word32 tmpProcessing[MAX_NUM_OBJECTS][L_FRAME48k]; - Word32 *pTmpProcessing[MAX_NUM_OBJECTS]; Word16 pos_idx; const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; const SPLIT_REND_WRAPPER *pSplitRendWrapper; @@ -6289,11 +6288,6 @@ static ivas_error renderIsmToSplitBinaural( /* Copy input audio to a processing buffer. */ copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing ); - FOR( i = 0; i < MAX_NUM_OBJECTS; i++ ) - { - pTmpProcessing[i] = tmpProcessing[i]; - } - FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { @@ -7977,12 +7971,6 @@ static ivas_error renderInputSba( SWITCH( getAudioConfigType( outConfig ) ) { -#ifdef SPLIT_REND_WITH_HEAD_ROT - case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: - case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: - error = renderSbaToSplitBinaural( sbaInput, outConfig, outAudio ); - break; -#endif case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: renderSbaToMc( sbaInput, outAudio ); BREAK; @@ -7992,6 +7980,12 @@ static ivas_error renderInputSba( case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL: SWITCH( outConfig ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED: + case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM: + error = renderSbaToSplitBinaural( sbaInput, outConfig, outAudio ); + break; +#endif case IVAS_AUDIO_CONFIG_BINAURAL: error = renderSbaToBinaural( sbaInput, outConfig, outAudio ); BREAK; -- GitLab From 344fd08b44401d56c67a3cd03b14590051b8b2f2 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 5 Feb 2025 16:47:48 +1100 Subject: [PATCH 16/43] linux error fixes, compiles locally --- Makefile | 2 +- Workspace_msvc/lib_lc3plus.vcxproj | 4 +- lib_lc3plus/al_fec.c | 116 +++++++++--------- lib_lc3plus/basop_mpy_lc3plus.h | 6 +- lib_lc3plus/basop_util_lc3plus.c | 2 +- lib_lc3plus/dct4_fx.c | 10 +- lib_lc3plus/detect_cutoff_warped_fx.c | 2 +- lib_lc3plus/fft_lc3plus.c | 26 ++-- lib_lc3plus/per_band_energy_fx.c | 6 +- ..._basop_util.c => rom_basop_util_lc3plus.c} | 8 +- ..._basop_util.h => rom_basop_util_lc3plus.h} | 6 +- 11 files changed, 94 insertions(+), 94 deletions(-) rename lib_lc3plus/{rom_basop_util.c => rom_basop_util_lc3plus.c} (99%) rename lib_lc3plus/{rom_basop_util.h => rom_basop_util_lc3plus.h} (98%) diff --git a/Makefile b/Makefile index 92d3cd3f0..5003f2cb2 100644 --- a/Makefile +++ b/Makefile @@ -230,7 +230,7 @@ endif $(CLI_APIPOSTREND): $(OBJS_CLI_APPPOSTREND) $(LIB_LIBISAR) $(LIB_LIBCOM) $(LIB_LIBUTIL) $(LIB_LIBDEBUG) $(LIB_LC3PLUS) ifeq "$(INCLUDE_SPLIT)" "1" - $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APPPOSTREND) -L. -lisar -livasutil -livasdebug -llc3plus -livascom $(LDLIBS) -o $(CLI_APIPOSTREND) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_CLI_APPPOSTREND) -L. -lisar -livasutil -livasdebug -livascom -llc3plus $(LDLIBS) -o $(CLI_APIPOSTREND) endif libs: $(LIB_LIBENC) $(LIB_LIBDEBUG) $(LIB_LIBCOM) $(LIB_LIBDEC) $(LIB_LIBREND) $(LIB_LIBISAR) $(LIB_LC3PLUS) $(LIB_LIBUTIL) diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index b22697021..22b5cddd3 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -164,7 +164,7 @@ - + @@ -183,7 +183,7 @@ - + diff --git a/lib_lc3plus/al_fec.c b/lib_lc3plus/al_fec.c index 7579a21b0..c659a90e0 100644 --- a/lib_lc3plus/al_fec.c +++ b/lib_lc3plus/al_fec.c @@ -11,7 +11,7 @@ #include "functions.h" -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" #include #include #include @@ -43,7 +43,7 @@ #define ERROR_REPORT_EP1_OK ((0x1000)>>1) #define ERROR_REPORT_EP2_OK ((0x2000)>>1) #define ERROR_REPORT_EP3_OK ((0x4000)>>1) -#define ERROR_REPORT_EP4_OK ((0x8000)>>1) +#define ERROR_REPORT_EP4_OK ((0x8000)>>1) #define ERROR_REPORT_ALL_OK (ERROR_REPORT_EP1_OK | ERROR_REPORT_EP2_OK | ERROR_REPORT_EP3_OK | ERROR_REPORT_EP4_OK) /* debugging switches */ @@ -781,7 +781,7 @@ int fec_decoder(UWord8 *iobuf, Word16 slot_bytes, int *data_bytes, Word16 *epmr, } } #endif - + IF (sub(*bfi, 1) == 0) { *data_bytes = 0; move16(); @@ -1060,7 +1060,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword n_mode_candidates = 0; move16(); risk_min_f.mantissa = SIMPLE_FLOAT_1_MANTISSA; move16(); risk_min_f.exponent = 0; move16(); - + IF (n_symb <= 80) { ep_risk_thresh.mantissa = EP_RISK_THRESH_NS_M; move16(); @@ -1071,16 +1071,16 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword ep_risk_thresh.mantissa = EP_RISK_THRESH_OS_M; move16(); ep_risk_thresh.exponent = EP_RISK_THRESH_OS_E; move16(); } - + syndr_calc[0] = &rs16_calculate_two_syndromes; syndr_calc[1] = &rs16_calculate_four_syndromes; syndr_calc[2] = &rs16_calculate_six_syndromes; - + FOR (i = 0; i < FEC_N_MODES; i++) { t[i] = (Word8)shr(sub(hamming_distance[i], 1), 1); move16(); } - + syndromes = my_scratch; my_scratch += FEC_TOTAL_SYNDROME_SIZE; elp = my_scratch; @@ -1091,25 +1091,25 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword my_scratch += FEC_TOTAL_ERROR_SIZE; deg_elp = (Word8 *)my_scratch; my_scratch += FEC_TOTAL_DEG_ELP_SIZE; - + *error_report = 0; move16(); *bfi = 0; move32(); - + /* mode detection (stage 1) */ codeword_length = get_codeword_length(n_codewords, n_symb, 0); - + epmr_position = sub(codeword_length, 1); - + rs16_calculate_two_syndromes(syndromes + SYNDROME_IDX(0, 0), iobuf, sub(codeword_length, 1)); - + IF (s_or(syndromes[0 + SYNDROME_IDX(0, 0)], syndromes[1 + SYNDROME_IDX(0, 0)]) == 0) { - + /* data validation for fec mode 1 */ *epmr = cw0_get_epmr(iobuf, epmr_position); - + dw0_bitswap(iobuf + 2, 1, n_symb / 2); - + IF (!crc1(iobuf + 8, sub(n_symb, 8), *epmr, iobuf + 2, 3, 1)) { mode = 0; move16(); @@ -1121,27 +1121,27 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { /* reverse bit swap */ dw0_bitswap(iobuf + 2, 1, n_symb / 2); - + *epmr = add(*epmr, 4); move16(); } } - + blacklist[0] = 1; move16(); - + /* mode detection (stage 2) */ - + /* calculate syndromes of code words 0 to 5 and modes 1 to 3 */ cw_offset = 0; move16(); - + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); - + rs16_calculate_six_syndromes(syndromes + SYNDROME_IDX(1, cw_counter), iobuf + cw_offset, sub(codeword_length, 1)); - + cw_offset = add(cw_offset, codeword_length); - + FOR (mode_counter = FEC_N_MODES - 1; mode_counter >= 1; mode_counter--) { FOR (i = 0; i < sub(hamming_distance[mode_counter], 1); i++) @@ -1168,14 +1168,14 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword n_broken_cw = add(n_broken_cw, 1); } } - + IF (n_broken_cw == 0) { mode = mode_counter; move16(); cw_offset = 0; move16(); - + *epmr = cw0_get_epmr(iobuf, epmr_position); - + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); @@ -1187,7 +1187,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } } - + IF (mode < 0) /* mode hasn't been detected so far -> errors occurred in transmission */ { /* calculate error locator polynomials for code words 0 to 5 */ @@ -1205,13 +1205,13 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } } - + /* risk analysis for mode candidate selection */ FOR (mode_counter = 1; mode_counter < FEC_N_MODES; mode_counter++) { dec_risk_f[mode_counter].mantissa = SIMPLE_FLOAT_1_MANTISSA; move16(); dec_risk_f[mode_counter].exponent = 0; move16(); - + IF (blacklist[mode_counter] == 0) { FOR (cw_counter = 0; cw_counter < 6; cw_counter++) @@ -1220,12 +1220,12 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword dec_risk_f[mode_counter], risk_table_f[mode_counter][deg_elp[DEG_ELP_IDX(mode_counter, cw_counter)]]); move16(); } - + IF (simple_float_cmp(dec_risk_f[mode_counter], ep_risk_thresh) <= 0) { mode_candidates[n_mode_candidates++] = mode_counter; move16(); } - + IF (simple_float_cmp(dec_risk_f[mode_counter], risk_min_f) < 0) { risk_min_f = dec_risk_f[mode_counter]; move16(); @@ -1233,13 +1233,13 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } assert(n_mode_candidates <= 4); // suppress false gcc warning when OPTIM=3 - + /* sort mode candidates by risk */ FOR (i = 0; i < n_mode_candidates; i++) { idx_min = i; move16(); val_min_f = dec_risk_f[mode_candidates[i]]; move16(); - + FOR (j = i + 1; j < n_mode_candidates; j++) { IF (simple_float_cmp(dec_risk_f[mode_candidates[j]], val_min_f) < 0) @@ -1248,24 +1248,24 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword idx_min = j; move16(); } } - + IF (sub(idx_min, i) > 0) - { + { tmp = mode_candidates[i]; move16(); mode_candidates[i] = mode_candidates[idx_min]; move16(); mode_candidates[idx_min] = tmp; move16(); } } - + /* try out candidate modes */ FOR (i = 0; i < n_mode_candidates; i++) { mode = mode_candidates[i]; move16(); - + FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); - + IF (deg_elp[DEG_ELP_IDX(mode, cw_counter)]) { IF (rs16_factorize_elp(err_pos + ERR_POS_IDX(mode, cw_counter), elp + ELP_IDX(mode, cw_counter), @@ -1283,34 +1283,34 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword BREAK; } } - + IF (mode < 0) { /* no decodable mode has been found */ *error_report = ERROR_REPORT_BEC_MASK; move16(); *bfi = 1; move32(); mode = -1; move16(); - + *epmr = fec_estimate_epmr_from_cw0(iobuf, t, syndromes, elp, deg_elp, err_pos, err_symb, n_codewords, n_symb); - + Dyn_Mem_Deluxe_Out(); return mode; } - + /* perform error correction */ cw_offset = 0; move16(); *error_report = 0; move16(); FOR (cw_counter = 0; cw_counter < 6; cw_counter++) { codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); - + IF (deg_elp[DEG_ELP_IDX(mode, cw_counter)]) { rs16_calculate_errors( err_symb + ERR_SYMB_IDX(mode, cw_counter), err_pos + ERR_POS_IDX(mode, cw_counter), syndromes + SYNDROME_IDX(mode, cw_counter), deg_elp[DEG_ELP_IDX(mode, cw_counter)], t[mode]); - + /* correct errors and sum up number of corrected bits */ FOR (i = 0; i < deg_elp[DEG_ELP_IDX(mode, cw_counter)]; i++) { @@ -1329,17 +1329,17 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword } } } - + FOR (i = 0; i <= EP_SIG_POLY_DEG; i++) { iobuf[cw_offset + i] = GF16_ADD(iobuf[cw_offset + i], sig_polys[mode][i]); } cw_offset = add(cw_offset, codeword_length); } - + /* set epmr according to risk value of cw0 */ epmr_dec_fail_increment = 8; - + IF (add(risk_table_f[mode][deg_elp[DEG_ELP_IDX(mode, 0)]].exponent, 8) <= 0) { epmr_dec_fail_increment = sub(epmr_dec_fail_increment, 4); @@ -1348,10 +1348,10 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { epmr_dec_fail_increment = sub(epmr_dec_fail_increment, 4); } - + *epmr = cw0_get_epmr(iobuf, epmr_position) + epmr_dec_fail_increment; } - + /* mode has been successfully detected -> now check and try to correct remaining code words*/ *n_pccw = fec_get_n_pccw(n_symb / 2, mode + 1, ccc_flag); IF (ccc_flag == 0) @@ -1363,15 +1363,15 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { n_pccw0 = 0; } - + FOR (cw_counter = 6; cw_counter < n_codewords; cw_counter++) { /* usual error correction scheme: syndromes -> elp's, errors, etc. */ codeword_length = get_codeword_length(n_codewords, n_symb, cw_counter); array_of_trust[n_codewords - 1 - cw_counter] = 1; move16(); - + syndr_calc[sub(t[mode], 1)](syndromes, iobuf + cw_offset, sub(codeword_length, 1)); - + deg_elp[0] = rs16_calculate_elp(elp, syndromes, t[mode]); move16(); FOR (i = 0; i < mode; i ++) @@ -1393,7 +1393,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword *error_report = ERROR_REPORT_BEC_MASK; move16(); mode = -1; move16(); *bfi = 1; move32(); - + BREAK; } ELSE @@ -1403,7 +1403,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword CONTINUE; } } - + IF (deg_elp[0]) { IF (rs16_factorize_elp(err_pos, elp, deg_elp[0], sub(codeword_length, 1))) @@ -1418,7 +1418,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword *error_report = ERROR_REPORT_BEC_MASK; move16(); mode = -1; move16(); *bfi = 1; move32(); - + BREAK; } ELSE @@ -1428,9 +1428,9 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword CONTINUE; } } - + rs16_calculate_errors(err_symb, err_pos, syndromes, deg_elp[0], t[mode]); - + /* correct errors and sum up number of corrected bits */ FOR (i = 0; i < deg_elp[0]; i++) { @@ -1459,7 +1459,7 @@ FEC_STATIC int rs16_detect_and_correct(UWord8 *iobuf, int n_symb, int n_codeword { return add(mode, 1); } - + return -1; } diff --git a/lib_lc3plus/basop_mpy_lc3plus.h b/lib_lc3plus/basop_mpy_lc3plus.h index 7c08755ee..72c7d91bb 100644 --- a/lib_lc3plus/basop_mpy_lc3plus.h +++ b/lib_lc3plus/basop_mpy_lc3plus.h @@ -9,8 +9,8 @@ #include "defines.h" -#ifndef __BASOP_MPY_H -#define __BASOP_MPY_H +#ifndef __BASOP_MPY_LC3PLUS_H +#define __BASOP_MPY_LC3PLUS_H #include "functions.h" @@ -91,4 +91,4 @@ void cplxMpy_32_16(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a void cplxMpy_32_32(Word32 *c_Re, Word32 *c_Im, const Word32 a_Re, const Word32 a_Im, const Word32 b_Re, const Word32 b_Im); -#endif /* __BASOP_SETTINGS_H */ +#endif /* __BASOP_MPY_LC3PLUS_H */ diff --git a/lib_lc3plus/basop_util_lc3plus.c b/lib_lc3plus/basop_util_lc3plus.c index e3ab30f70..9f2d6be79 100644 --- a/lib_lc3plus/basop_util_lc3plus.c +++ b/lib_lc3plus/basop_util_lc3plus.c @@ -9,7 +9,7 @@ #include "defines.h" #include "functions.h" -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" #include "basop_util_lc3plus.h" extern const Word32 SqrtTable_lc3plus[32]; diff --git a/lib_lc3plus/dct4_fx.c b/lib_lc3plus/dct4_fx.c index 9f12894f4..dca4e382c 100644 --- a/lib_lc3plus/dct4_fx.c +++ b/lib_lc3plus/dct4_fx.c @@ -8,7 +8,7 @@ ******************************************************************************/ #include "functions.h" -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ @@ -20,7 +20,7 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ # endif #endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ Word32 *workBuffer) /* : size of L */ - + { Word16 sin_step; Word16 idx; @@ -132,12 +132,12 @@ void dct_IV(Word32 *pDat, /* i/o: pointer to data buffer */ #ifdef ENABLE_DCTIV_RESCALE # ifdef CR8_F_ADAPT_MDCT_DCT_PRECISION - if (hrmode) + if (hrmode) # endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ { - + scale = s_max(getScaleFactor32_lc3plus(pDat, L), 0); move16(); - + FOR (i = 0; i < L; i++) { pDat[i] = L_shl_pos(pDat[i], scale); move32(); diff --git a/lib_lc3plus/detect_cutoff_warped_fx.c b/lib_lc3plus/detect_cutoff_warped_fx.c index b6ef25472..adbf04afa 100644 --- a/lib_lc3plus/detect_cutoff_warped_fx.c +++ b/lib_lc3plus/detect_cutoff_warped_fx.c @@ -8,7 +8,7 @@ ******************************************************************************/ #include "functions.h" -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" void processDetectCutoffWarped_fx(Word16 *bw_idx, Word32 *d2_fx, Word16 d2_fx_exp, Word16 fs_idx, Word16 frame_dms) { diff --git a/lib_lc3plus/fft_lc3plus.c b/lib_lc3plus/fft_lc3plus.c index a86286d04..6db6de7bb 100644 --- a/lib_lc3plus/fft_lc3plus.c +++ b/lib_lc3plus/fft_lc3plus.c @@ -6,9 +6,9 @@ * Rights Policy, 3rd April 2019. No patent licence is granted by implication, * * estoppel or otherwise. * ******************************************************************************/ - + #include "functions.h" -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" #ifdef ENABLE_FFT_RESCALE #ifndef FFT_RESCALE_HR @@ -1085,7 +1085,7 @@ static void fft15(Word32 *re, Word32 *im, Word16 s) } #ifdef CR8_G_ADD_75MS - + #define STC(x) (x) const Word32 RotVectorReal12[] = { @@ -1104,7 +1104,7 @@ const Word32 RotVectorImag12[] = STC(0x7fffffff), STC(0x00000000), #endif }; - + static void fft12(Word32 *pInput) { Dyn_Mem_Deluxe_In(Word32 aDst[24]; Word32 * pSrc, *pDst; Counter i; Word32 r1, r2, s1, s2, pD; Word32 re, im; @@ -1141,7 +1141,7 @@ static void fft12(Word32 *pInput) pDst[5] = L_sub(s1, r2); pSrc += 2; pDst += 6; - + const Word32 *pVecRe = RotVectorReal12; const Word32 *pVecIm = RotVectorImag12; @@ -1176,7 +1176,7 @@ static void fft12(Word32 *pInput) vre = *pVecRe++; vim = *pVecIm++; cplxMpy_32_32(&pDst[3], &pDst[2], im, re, vre, vim); - + re = L_add(r1, s2); im = L_sub(s1, r2); @@ -3766,7 +3766,7 @@ static void fftN2(Word32 *re, Word32 *im, { fft15(&x[i * 2 * dim1], &x[i * 2 * dim1 + 1], 2); } - + BREAK; case 16: FOR (i = 0; i < dim2; i++) @@ -3808,7 +3808,7 @@ static void fftN2(Word32 *re, Word32 *im, #endif default: ASSERT(0); } - + #ifdef ENABLE_FFT_RESCALE IF (scale) { @@ -3878,7 +3878,7 @@ static void fftN2(Word32 *re, Word32 *im, im[sx * i + sx * 3 * dim1] = L_add(t03, t07); move32(); } - + BREAK; } @@ -3927,7 +3927,7 @@ static void fftN2(Word32 *re, Word32 *im, BREAK; } #endif - + case 8: { Word32 x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14, x15; @@ -4084,7 +4084,7 @@ static void fftN2(Word32 *re, Word32 *im, } BREAK; } - + #if defined(ENABLE_HR_MODE) case 16: { @@ -4093,7 +4093,7 @@ static void fftN2(Word32 *re, Word32 *im, { cplxMpy4_16_1(y[2 * j], y[2 * j + 1], x[2 * 0 + 2 * j * dim1], x[2 * 0 + 2 * j * dim1 + 1]); } - + fft16(&y[0], &y[1], 2); FOR (j = 0; j < dim2; j++) { @@ -4333,7 +4333,7 @@ void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 length, Word16 s, Word16 #ifndef ENABLE_FFT_30X16 fftN2(re, im, RotVector_960, 60, 8, s, 2, 120, scratch); #else - fftN2(re, im, RotVector_30_16, 30, 16, s, 2, 60, scratch); + fftN2(re, im, RotVector_30_16, 30, 16, s, 2, 60, scratch); #endif *scale = add(*scale, SCALEFACTOR480); move16(); #else diff --git a/lib_lc3plus/per_band_energy_fx.c b/lib_lc3plus/per_band_energy_fx.c index 14e853212..3ba629a83 100644 --- a/lib_lc3plus/per_band_energy_fx.c +++ b/lib_lc3plus/per_band_energy_fx.c @@ -8,7 +8,7 @@ ******************************************************************************/ #include "functions.h" -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Word16 d_fx_exp, const Word16 *band_offsets, Word16 fs_idx, Word16 n_bands, Word16 linear, Word16 frame_dms, @@ -78,7 +78,7 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor IF (sub(linear, 1) == 0) { - + #ifdef ENABLE_HR_MODE if (hrmode) { @@ -230,7 +230,7 @@ void processPerBandEnergy_fx(Word32 *d2_fx, Word16 *d2_fx_exp, Word32 *d_fx, Wor /* specify headroom, it can be reduced by one due to use of L_mac0 */ s2 = sub(s1, bands_nrg_scale[nbands]); #endif - + /* calculate energy per band */ nrg = 0; move32(); diff --git a/lib_lc3plus/rom_basop_util.c b/lib_lc3plus/rom_basop_util_lc3plus.c similarity index 99% rename from lib_lc3plus/rom_basop_util.c rename to lib_lc3plus/rom_basop_util_lc3plus.c index e37b4bfad..45629965d 100644 --- a/lib_lc3plus/rom_basop_util.c +++ b/lib_lc3plus/rom_basop_util_lc3plus.c @@ -7,7 +7,7 @@ * estoppel or otherwise. * ******************************************************************************/ -#include "rom_basop_util.h" +#include "rom_basop_util_lc3plus.h" #include "basop_util_lc3plus.h" #include "functions.h" @@ -1197,7 +1197,7 @@ const PWord32 SineWindow720[360] = { WTCP(0x5b00814c, 0x5a03c172), WTCP(0x5ace2d0e, 0x5a36869f), WTCP(0x5a9bbc7c, 0x5a692fa7) }; #endif - + const PWord32 SineWindow960[480] = { WTCP(0x7ffffd30, 0x001aceea), WTCP(0x7fffe6bb, 0x00506cb9), WTCP(0x7fffb9d0, 0x00860a79), WTCP(0x7fff7670, 0x00bba822), WTCP(0x7fff1c9a, 0x00f145ab), WTCP(0x7ffeac4f, 0x0126e309), @@ -1361,7 +1361,7 @@ const PWord32 SineWindow960[480] = { WTCP(0x5ae10ff8, 0x5a237ff9), WTCP(0x5abb4628, 0x5a49894f), WTCP(0x5a956c6d, 0x5a6f82cd), }; # endif - + // fs 48 32 24 16 8 // ms +-------------------- // 10.0 | 480 320 240 160 80 @@ -2009,7 +2009,7 @@ const Word32 RotVector_720[2 * (720 - 30)] = { SHC(0x4654552e), SHC(0x465f4350), SHC(0x3078303d), SHC(0x40755c3d), SHC(0x00202477), SHC(0x56524553), SHC(0x454d414e), SHC(0x4c564c48), SHC(0x3d454d4f), SHC(0x732f7372), SHC(0x4e474f4c), SHC(0x6d676c73), SHC(0x59414c50), SHC(0x74617669), SHC(0x6f632f70), SHC(0x2e656c70), SHC(0x2e646863), SHC(0x53386438) - }; + }; #endif const Word32 RotVector_960[2 * (480 - 60)] = { SHC(0x7fffffff), SHC(0x00000000), SHC(0x7ffd3154), SHC(0xfe531484), SHC(0x7ff4c56f), SHC(0xfca63bd8), diff --git a/lib_lc3plus/rom_basop_util.h b/lib_lc3plus/rom_basop_util_lc3plus.h similarity index 98% rename from lib_lc3plus/rom_basop_util.h rename to lib_lc3plus/rom_basop_util_lc3plus.h index 6e757c339..11d90c77b 100644 --- a/lib_lc3plus/rom_basop_util.h +++ b/lib_lc3plus/rom_basop_util_lc3plus.h @@ -7,8 +7,8 @@ * estoppel or otherwise. * ******************************************************************************/ -#ifndef __BASOP_UTIL_ROM_H__ -#define __BASOP_UTIL_ROM_H__ +#ifndef __ROM_BASOP_UTIL_LC3PLUS_H__ +#define __ROM_BASOP_UTIL_LC3PLUS_H__ #include "basop_util_lc3plus.h" #include "functions.h" @@ -69,7 +69,7 @@ void BASOP_getTables( #else const PWord16 **ptwiddle, const PWord16 **sin_twiddle, -#endif +#endif Word16 *sin_step, Word16 length); -- GitLab From bf593d4ef4f67559a74472b3a1259a6c1ff30083 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 5 Feb 2025 12:16:39 +0100 Subject: [PATCH 17/43] do not passs "BASOP" as project to prepare_instrumentation.sh this was added to skip missing split rendering/LC3Plus code parts which are now there --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2cb080114..479a000a6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -901,7 +901,7 @@ build-codec-linux-instrumented-make: script: - *print-common-info - *update-scripts-repo - - bash scripts/prepare_instrumentation.sh -m MEM_ONLY -p BASOP + - bash scripts/prepare_instrumentation.sh -m MEM_ONLY - make -j -C $INSTR_DIR @@ -1655,7 +1655,7 @@ ivas-pytest-on-merge-request: stage: test variables: ret_val: 0 - GET_WMOPS_ARGS: "mem_only basop" + GET_WMOPS_ARGS: "mem_only" timeout: 3 hours 30 minutes before_script: - *print-common-info -- GitLab From 8b94edb889c5fefe9518eccf00ef3f458dd7b25b Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 5 Feb 2025 12:35:39 +0100 Subject: [PATCH 18/43] remove obsolete anchor + add clean step --- .gitlab-ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 479a000a6..3995083d3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -132,10 +132,6 @@ stages: echo "Commit time was $CI_COMMIT_TIMESTAMP" ("echo 'System time is'", "Get-Date -Format 'dddd dd/MM/yyyy HH:mm K'") | Invoke-Expression -.disable-debugging-macro: &disable-debugging-macro - # automatically disable #DEBUGGING macro in options.h using /**/-comment - - sed -i.bak -e "s/^[[:space:]]*\(#define[[:space:]]*DEBUGGING\)/\/\*\1\*\//g" lib_com/options.h - # From float CI .mr-fetch-target-branch: &mr-fetch-target-branch # first delete local target branch to avoid conflicts when branch is cached and there are merge conflicts during fetching @@ -151,7 +147,6 @@ stages: # From float CI .merge-request-comparison-setup-codec: &merge-request-comparison-setup-codec ### build test binaries, initial clean for paranoia reasons - - *disable-debugging-macro - make clean - make -j - mv IVAS_cod IVAS_cod_test @@ -169,7 +164,7 @@ stages: - echo "Building reference codec at commit $target_commit" ### build reference binaries - - *disable-debugging-macro + - make clean - make -j - mv IVAS_cod IVAS_cod_ref - mv IVAS_dec IVAS_dec_ref -- GitLab From b93b23114f47c96272a1e31677917df6a6b9cb6a Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 5 Feb 2025 12:46:13 +0100 Subject: [PATCH 19/43] correct rule for build job with DEBUGGING active --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3995083d3..4fe5ec338 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -937,7 +937,7 @@ build-codec-linux-debugging-make: rules: - if: $CI_PIPELINE_SOURCE == 'web' - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" # only have MR pipelines for MRs to main + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_PIPELINE_SOURCE == 'schedule' - if: $CI_PIPELINE_SOURCE == 'push' when: never -- GitLab From d406d0e1fcaad3f5c3b26a30a72220325e6448d8 Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 6 Feb 2025 10:00:10 +1100 Subject: [PATCH 20/43] debug compilation fix --- lib_isar/lib_isar_post_rend.c | 3 ++- lib_rend/ivas_stat_rend.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib_isar/lib_isar_post_rend.c b/lib_isar/lib_isar_post_rend.c index 128675281..768b23089 100644 --- a/lib_isar/lib_isar_post_rend.c +++ b/lib_isar/lib_isar_post_rend.c @@ -1792,10 +1792,11 @@ ivas_error ISAR_POST_REND_getSamples( } #ifndef DISABLE_LIMITER + Word32 limiter_thresold; #ifdef DEBUGGING hIvasRend->numClipping += #endif - Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); + limiter_thresold = L_shl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact ); limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact ); #endif diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index 76e5633fc..ea4d0015a 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1475,6 +1475,10 @@ typedef struct Word32 release_heuristic_fx; /* Q30 */ Word32 attack_constant_fx; /* Q31 */ Word16 strong_saturation_count; +#ifdef DEBUGGING + int32_t cnt_frames_limited; /* counter of frames in which the limiter is applied */ +#endif + } IVAS_LIMITER, *IVAS_LIMITER_HANDLE; -- GitLab From 199c69ea70ac103aacd7519cf411417ae0618e53 Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 6 Feb 2025 10:46:25 +1100 Subject: [PATCH 21/43] temporary fix to disable WMOPS in lc3plus to pass instrumentation build --- lib_lc3plus/basop_util_lc3plus.h | 8 +- lib_lc3plus/dec_lc3.c | 94 ++++++++++---------- lib_lc3plus/enc_lc3.c | 112 ++++++++++++------------ lib_lc3plus/functions.h | 1 + lib_lc3plus/plc_classify_fx.c | 16 ++-- lib_lc3plus/plc_phecu_fec_hq_fx.c | 106 +++++++++++----------- lib_lc3plus/plc_phecu_peak_locator_fx.c | 4 +- lib_lc3plus/plc_phecu_setf0hz_fx.c | 4 +- lib_lc3plus/plc_phecu_tools_fx.c | 44 +++++----- lib_lc3plus/plc_update_aft_imdct_fx.c | 78 ++++++++--------- lib_lc3plus/plc_update_fx.c | 100 ++++++++++----------- lib_lc3plus/plc_xcorr_fx.c | 8 +- lib_lc3plus/pvq_enc_fx.c | 4 +- lib_lc3plus/pvq_index_fx.c | 8 +- lib_lc3plus/sns_quantize_scf_fx.c | 20 ++--- 15 files changed, 304 insertions(+), 303 deletions(-) diff --git a/lib_lc3plus/basop_util_lc3plus.h b/lib_lc3plus/basop_util_lc3plus.h index 5f4f5c56b..f22d531cf 100644 --- a/lib_lc3plus/basop_util_lc3plus.h +++ b/lib_lc3plus/basop_util_lc3plus.h @@ -316,14 +316,14 @@ void BASOP_cfft_lc3plus(Word32 *re, Word32 *im, Word16 sizeOfFft, Word16 s, Word void BASOP_rfftN(Word32 *re, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer); void BASOP_irfftN(Word32 *re, Word16 sizeOfFft, Word16 *scale, Word8 *scratchBuffer); -#if WMOPS +#if WMOPS_LC3PLUS extern BASIC_OP multiCounter[MAXCOUNTERS]; extern int currCounter; #endif static __inline void basop_memcpy(void *dst, const void *src, size_t n) { -#if WMOPS +#if WMOPS_LC3PLUS multiCounter[currCounter].move16 += (UWord32)n / 2; #endif /* check for overlapping memory */ @@ -333,7 +333,7 @@ static __inline void basop_memcpy(void *dst, const void *src, size_t n) static __inline void basop_memmove(void *dst, const void *src, size_t n) { -#if WMOPS +#if WMOPS_LC3PLUS multiCounter[currCounter].move16 += (UWord32)n / 2; #endif memmove(dst, src, n); @@ -341,7 +341,7 @@ static __inline void basop_memmove(void *dst, const void *src, size_t n) static __inline void basop_memset(void *dst, int val, size_t n) { -#if WMOPS +#if WMOPS_LC3PLUS multiCounter[currCounter].move16 += (UWord32)n / 2; #endif memset(dst, val, n); diff --git a/lib_lc3plus/dec_lc3.c b/lib_lc3plus/dec_lc3.c index 40818106e..59a061862 100644 --- a/lib_lc3plus/dec_lc3.c +++ b/lib_lc3plus/dec_lc3.c @@ -148,7 +148,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s memset(q_d_fx, 0, decoder->frame_length * sizeof(*q_d_fx)); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Decoder"); #endif @@ -164,18 +164,18 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s if (bfi != 1) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("Dec(bfi=0)"); #endif } else { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("Dec(bfi=1)"); #endif } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Entropy dec"); #endif IF (sub(bfi, 1) != 0) @@ -186,11 +186,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s BW_cutoff_idx_nf = BW_cutoff_idx; move16(); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); /* Entropy dec */ #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Ari dec"); #endif IF (sub(bfi, 1) != 0) @@ -243,11 +243,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s processAriDecoderScaling_fx(sqQdec, decoder->yLen, q_d_fx, &q_fx_exp); } } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); /* Ari dec */ #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("SnsQuantScfDec"); #endif IF (sub(bfi, 1) != 0) @@ -260,11 +260,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s processSnsQuantizeScfDecoder_fx(L_scf_idx, scf_q, currentScratch); #endif } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("PLC::ComputeStabFac"); #endif if (h_DecSetup->plcAd) @@ -272,11 +272,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s processPLCcomputeStabFac_main(scf_q, h_DecSetup->plcAd->old_scf_q, h_DecSetup->plcAd->old_old_scf_q, bfi, h_DecSetup->prev_bfi, h_DecSetup->prev_prev_bfi, &h_DecSetup->plcAd->stab_fac); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Partial Concealment"); #endif IF (sub(bfi, 1) != 0) @@ -295,13 +295,13 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s &h_DecSetup->prev_gg_e, &BW_cutoff_idx_nf, &h_DecSetup->prev_BW_cutoff_idx_nf, fac_ns_idx, &h_DecSetup->prev_fac_ns_fx, &h_DecSetup->pc_nbLostFramesInRow); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif IF (sub(bfi, 1) != 0) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Residual dec"); #endif processResidualDecoding_fx(q_d_fx, q_fx_exp, decoder->yLen, resBitBuf, fill_bits @@ -309,11 +309,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s , decoder->hrmode #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Noisefill"); #endif /* currentScratch Size = 2 * MAX_LEN bytes */ @@ -326,19 +326,19 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #endif ); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("applyGlobalGain"); #endif processApplyGlobalGain_fx(q_d_fx, &q_fx_exp, decoder->yLen, gg_idx, h_DecSetup->quantizedGainOff); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Tns_dec"); #endif /* currentScratch Size = 48 bytes */ @@ -348,45 +348,45 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s , decoder->hrmode #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif #ifdef ENABLE_HR_MODE -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("SnsInterpScfDec"); #endif processSnsInterpolateScf_fx(scf_q_ip, int_scf_fx_ip, int_scf_fx_exp, 0, decoder->bands_number, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Mdct shaping_dec"); #endif processScfScaling(int_scf_fx_exp, decoder->bands_number, &q_fx_exp); processMdctShaping_fx(q_d_fx, int_scf_fx_ip, int_scf_fx_exp, decoder->bands_offset, decoder->bands_number); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif #else -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("SnsInterpScfDec"); #endif /* currentScratch Size = 128 bytes */ processSnsInterpolateScf_fx(scf_q, int_scf_fx, int_scf_fx_exp, 0, decoder->bands_number, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Mdct shaping_dec"); #endif processScfScaling(int_scf_fx_exp, decoder->bands_number, &q_fx_exp); processMdctShaping_fx(q_d_fx, int_scf_fx, int_scf_fx_exp, decoder->bands_offset, decoder->bands_number); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* end int_scf_fx */ @@ -406,7 +406,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s } #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("PLC::Main"); #endif /* currentScratch Size = 2 * MAX_LGW + 8 * MAX_LPROT + 12 * MAX_L_FRAME */ @@ -432,7 +432,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s , decoder->alpha_type_2_table #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif @@ -446,7 +446,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s } #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("PLC/PC::DampingScrambling"); #endif if (h_DecSetup->plcAd) @@ -462,11 +462,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s #endif ); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Imdct"); #endif /* currentScratch Size = 4 * MAX_LEN */ @@ -499,11 +499,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s } #endif /* ENABLE_HR_MODE */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("PLC::Update"); #endif @@ -514,11 +514,11 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s , decoder->hrmode #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("LtpfDec"); #endif /* currentScratch Size = 0.5 * MAX_LEN + 20 bytes */ @@ -533,7 +533,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s &h_DecSetup->rel_pitch_change, decoder->hrmode, decoder->frame_dms, #endif currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif @@ -547,7 +547,7 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s } #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Output scaling"); #endif { @@ -579,15 +579,15 @@ static int Dec_LC3PLUS_Channel(LC3PLUS_Dec *decoder, int channel, int bits_per_s } } } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); /* Output scaling */ #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); /* Decoder */ #endif @@ -623,7 +623,7 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, vo { fec_num_bytes = num_bytes; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("fec_dec"); #endif @@ -632,7 +632,7 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, vo &decoder->n_pccw, &bfi, &decoder->be_bp_left, &decoder->be_bp_right, &decoder->n_pc, &decoder->m_fec, scratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif @@ -668,7 +668,7 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, vo { fec_num_bytes = num_bytes / decoder->channels + (ch < (num_bytes % decoder->channels)); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("fec_dec"); #endif @@ -679,7 +679,7 @@ LC3PLUS_Error Dec_LC3PLUS(LC3PLUS_Dec *decoder, UWord8 *input, int num_bytes, vo &decoder->n_pccw, &channel_bfi, &decoder->be_bp_left, &decoder->be_bp_right, &decoder->n_pc, &decoder->m_fec, scratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif diff --git a/lib_lc3plus/enc_lc3.c b/lib_lc3plus/enc_lc3.c index 30ff9971b..ada4bf87e 100644 --- a/lib_lc3plus/enc_lc3.c +++ b/lib_lc3plus/enc_lc3.c @@ -61,7 +61,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ # endif #endif /* CR8_F_ADAPT_MDCT_DCT_PRECISION */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Encoder"); #endif @@ -134,7 +134,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ /* Scale 24-bit input data */ IF (sub(bits_per_sample, 24) == 0) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Scale_signal24"); #endif scale_signal24_fx(s_in, s_in_scaled, &h_EncSetup->x_exp, h_EncSetup->stEnc_mdct_mem, @@ -142,7 +142,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ h_EncSetup->r12k8_mem_50, h_EncSetup->r12k8_mem_out, encoder->r12k8_mem_out_len, h_EncSetup->mdct_mem32, encoder->frame_length, h_EncSetup->resamp_mem32, h_EncSetup->olpa_mem_s12k8, &h_EncSetup->resamp_exp); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif } @@ -161,7 +161,7 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #endif } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Mdct"); #endif @@ -174,12 +174,12 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #endif encoder->W_fx, encoder->W_size, h_EncSetup->stEnc_mdct_mem, encoder->stEnc_mdct_mem_len, d_fx, &d_fx_exp, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* begin s_12k8 */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Resamp12k8"); #endif /* currentScratch Size = 2.25 * MAX_LEN bytes */ @@ -198,11 +198,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ , bits_per_sample ); #endif /* ENABLE_HR_MODE */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Olpa"); #endif /* currentScratch Size = 392 bytes */ @@ -212,11 +212,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ &h_EncSetup->pitch_flag, #endif h_EncSetup->resamp_exp, encoder->frame_dms, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("LtpfEnc"); #endif /* currentScratch Size = 512 bytes */ @@ -229,12 +229,12 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ ,encoder->hrmode #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* end s_12k8 */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("AttackDetector"); #endif /* currentScratch Size = ??? bytes */ @@ -243,12 +243,12 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #else attack_detector_fx(encoder, h_EncSetup, s_in_scaled, sub(h_EncSetup->x_exp, 15), currentScratch); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* begin ener_fx */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("PerBandEnergy"); #endif /* currentScratch Size = 160 bytes */ @@ -258,11 +258,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ , encoder->hrmode #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Near Nyquist Detector"); #endif /* Near Nyquist Detector */ @@ -283,10 +283,10 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ h_EncSetup->ltpf_mem_ltpf_on = 0; move16(); ltpf_idx[1] = 0; move16(); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("BW Cutoff-Detection"); #endif IF (h_EncSetup->lfe == 0) @@ -311,11 +311,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ { BW_cutoff_idx = 0; } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("SnsCompScf"); #endif @@ -324,39 +324,39 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ processSnsComputeScf_fx(ener_fx, ener_fx_exp, encoder->fs_idx, encoder->bands_number, scf, h_EncSetup->attdec_detected, encoder->attdec_damping, currentScratch, encoder->sns_damping ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("SnsQuantScfEnc"); #endif /* currentScratch Size = 500 bytes */ processSnsQuantizeScfEncoder_fx(scf, L_scf_idx, scf_q, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("SnsInterpScfEnc"); #endif /* currentScratch Size = 128 bytes */ processSnsInterpolateScf_fx(scf_q, int_scf_fx, int_scf_fx_exp, 1, encoder->bands_number, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Mdct shaping_enc"); #endif processMdctShaping_fx(d_fx, int_scf_fx, int_scf_fx_exp, encoder->bands_offset, encoder->bands_number); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* end int_scf_fx_exp */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("BandwidthControl_enc"); #endif if (encoder->bandwidth < L_shr_pos(encoder->fs, 1)) @@ -364,10 +364,10 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ process_cutoff_bandwidth(d_fx, encoder->yLen, encoder->bw_ctrl_cutoff_bin); BW_cutoff_idx = s_min(BW_cutoff_idx, encoder->bw_index); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Tns_enc"); #endif /* currentScratch Size = 2 * MAX_LEN + 220 */ @@ -392,11 +392,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ h_EncSetup->tns_bits = tns_numfilters; move16(); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Est. Global Gain"); #endif /* currentScratch Size = 4 * MAX_LEN bytes */ @@ -430,12 +430,12 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ , encoder->hrmode, h_EncSetup->regBits, encoder->frame_dms #endif ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* begin q_d_fx16 */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Quant. 1"); #endif #ifdef ENABLE_HR_MODE @@ -448,11 +448,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ h_EncSetup->targetBitsAri, &h_EncSetup->mem_specBits, &nBits, encoder->fs_idx, &lastnz, codingdata, &lsbMode, -1); #endif /* ENABLE_HR_MODE */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Adj. Global Gain"); #endif #ifdef ENABLE_HR_MODE @@ -466,11 +466,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ processAdjustGlobalGain_fx(&quantizedGain, quantizedGainMin, h_EncSetup->quantizedGainOff, &gain, &gain_e, h_EncSetup->targetBitsQuant, h_EncSetup->mem_specBits, &gainChange, encoder->fs_idx); #endif /* ENABLE_HR_MODE */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Quant. 2"); #endif IF (sub(gainChange, 1) == 0) @@ -485,11 +485,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ 0); #endif /* ENABLE_HR_MODE */ } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Res. Cod."); #endif IF (lsbMode == 0) @@ -516,11 +516,11 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ numResBits = 0; move16(); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Noise fac"); #endif /* currentScratch Size = 2 * MAX_LEN bytes */ @@ -543,21 +543,21 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ fac_ns_idx = 7; move16(); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Entropy cod"); #endif processEncoderEntropy(bytes, &bp_side, &mask_side, h_EncSetup->targetBitsAri, h_EncSetup->targetBytes, encoder->yLen, encoder->BW_cutoff_bits, tns_numfilters, lsbMode, lastnz, tns_order, fac_ns_idx, quantizedGain, BW_cutoff_idx, ltpf_idx, L_scf_idx, bfi_ext, encoder->fs_idx); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Ari cod"); #endif processAriEncoder_fx(bytes, bp_side, mask_side, h_EncSetup->targetBitsAri, @@ -568,17 +568,17 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ #endif tns_order, tns_numfilters, indexes, lastnz, codingdata, resBits, numResBits, lsbMode, h_EncSetup->enable_lpc_weighting, currentScratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Reorder Bitstream Enc"); #endif test(); IF (encoder->combined_channel_coding == 0 && h_EncSetup->n_pc > 0) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("Reorder Ari dec"); #endif @@ -606,17 +606,17 @@ static void Enc_LC3PLUS_Channel(LC3PLUS_Enc *encoder, int channel, int bits_per_ ); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); /* Ari dec */ #endif processReorderBitstream_fx(bytes, h_EncSetup->n_pccw, h_EncSetup->n_pc, b_left, currentScratch); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif /* end q_d_fx16 */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif @@ -638,14 +638,14 @@ int Enc_LC3PLUS(LC3PLUS_Enc *encoder, void **input, int bits_per_sample, UWord8 if (encoder->epmode && encoder->combined_channel_coding == 0) { output_size2 = totalBytes / encoder->channels + (ch < (totalBytes % encoder->channels)); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("fec_enc"); #endif fec_encoder(encoder->epmode, encoder->epmr, lc3buf, encoder->channel_setup[ch]->targetBytes, output_size2, encoder->channel_setup[ch]->n_pccw, scratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif @@ -663,14 +663,14 @@ int Enc_LC3PLUS(LC3PLUS_Enc *encoder, void **input, int bits_per_sample, UWord8 { input_size = output_size; output_size = (Word32)encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_start("fec_enc"); #endif fec_encoder(encoder->epmode, encoder->epmr, output, input_size, output_size, encoder->channel_setup[0]->n_pccw, scratch); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_end(); #endif } diff --git a/lib_lc3plus/functions.h b/lib_lc3plus/functions.h index 90571c6cd..940c58da7 100644 --- a/lib_lc3plus/functions.h +++ b/lib_lc3plus/functions.h @@ -833,4 +833,5 @@ void *balloc(void *base, size_t *base_size, size_t size); Word16 type_2_fadeout_fx(Word16 nbLostFramesInRow, Word16 frame_dms); #endif + #endif diff --git a/lib_lc3plus/plc_classify_fx.c b/lib_lc3plus/plc_classify_fx.c index bbb01826a..d30b516a4 100644 --- a/lib_lc3plus/plc_classify_fx.c +++ b/lib_lc3plus/plc_classify_fx.c @@ -45,7 +45,7 @@ static void array_insert_and_shift(Word32 *array, UWord8 value, Word16 longterm_ { Word32 current_byte = 0; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PLC::array_insert_and_shift"); #endif @@ -58,7 +58,7 @@ static void array_insert_and_shift(Word32 *array, UWord8 value, Word16 longterm_ current_byte = change_bit_at_position(current_byte, *bit_position, value); array[*byte_position] = current_byte; move16(); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -73,7 +73,7 @@ static void array_calculate(Word32 *array_tdc, Word32 *array_ns, int length, Wor Word32 current_byte_tdc = 0, current_byte_ns = 0; Word16 counter_loc_tdc = 0, counter_loc_ns = 0, counter_tmp = 0; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PLC::array_calculate"); #endif @@ -104,7 +104,7 @@ static void array_calculate(Word32 *array_tdc, Word32 *array_ns, int length, Wor #ifndef CR9_L_RETRAIN_FADEOUT_TYPE_CLASSIFIER *counter_phecu = sub(sub(overall_counter, counter_loc_tdc), counter_loc_ns); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -130,7 +130,7 @@ void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLost Word32 class; ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PLC::processPLCclassify_fx"); #endif @@ -246,7 +246,7 @@ void processPLCclassify_fx(Word16 plcMeth, Word16 *concealMethod, Word16 *nbLost } Dyn_Mem_Deluxe_Out(); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -268,7 +268,7 @@ Word16 spectral_centroid_fx_lc(Word16 old_scf_q[], const Word16 *band_offsets, W Word16 *old_scf_q_mod_exp; Word16 *band_offsets_local; ); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PLC::spectral_centroid_fx_lc"); #endif @@ -415,7 +415,7 @@ Word16 spectral_centroid_fx_lc(Word16 old_scf_q[], const Word16 *band_offsets, W # endif Dyn_Mem_Deluxe_Out(); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return sc; diff --git a/lib_lc3plus/plc_phecu_fec_hq_fx.c b/lib_lc3plus/plc_phecu_fec_hq_fx.c index ca2a345f4..aaf6a9bd0 100644 --- a/lib_lc3plus/plc_phecu_fec_hq_fx.c +++ b/lib_lc3plus/plc_phecu_fec_hq_fx.c @@ -127,12 +127,12 @@ static Word16 plc_phEcu_nonpure_tone_ana_fx(const Word16* plocs, const Word16 static void rotate_W16_fx(Word16 re_in, Word16 im_in, Word16 cosFactor, Word16 sinFactor, Word16 *re_out_ptr, Word16 *im_out_ptr) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::rotate_W16_fx"); #endif *re_out_ptr = msu_r(L_mult(re_in, cosFactor), im_in, sinFactor); /* 2 ops no move when inlined */ *im_out_ptr = mac_r(L_mult(re_in, sinFactor), im_in, cosFactor); /* 2 ops no move when inlined */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return; @@ -141,7 +141,7 @@ static void rotate_W16_fx(Word16 re_in, Word16 im_in, Word16 cosFactor, Word16 s static void valley_magnitude_adj_fx(Word16 *re_ptr, Word16 *im_ptr, Word16 uniFactor, Word16 cosFactor) { Word16 scale_fx; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::valley_magnitude_adj_fx"); #endif @@ -158,7 +158,7 @@ static void valley_magnitude_adj_fx(Word16 *re_ptr, Word16 *im_ptr, Word16 uniFa *re_ptr = mult_r(scale_fx, shl_sat(*re_ptr, 1)); /* no moves , should be inlined */ *im_ptr = mult_r(scale_fx, shl_sat(*im_ptr, 1)); /* no moves , should be inlined */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return; @@ -188,7 +188,7 @@ Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F) })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::rand_phase_fx"); #endif @@ -201,7 +201,7 @@ Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F) #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return seed2; @@ -354,13 +354,13 @@ void trans_burst_ana_fx( if (time_offs == 0) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::trans_burst_ana_fx(1st)"); #endif } else { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::trans_burst_ana_fx(N)"); #endif } @@ -699,7 +699,7 @@ void trans_burst_ana_fx( L_acc = L_sub((INT32_MAX >> 1) + 1, L_mult0(alpha[k], alpha[k])); { - /* use lower complex(WMOPS/ROM) 2nd-order sqrt approximation */ + /* use lower complex(WMOPS_LC3PLUS/ROM) 2nd-order sqrt approximation */ Word32 L_man, L_acc2 = L_acc; Word16 tmp, expo_in, expo2, man_in, man; /* updated code using the 2nd order approximation routine */ @@ -797,7 +797,7 @@ void trans_burst_ana_fx( #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -826,7 +826,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::imax_fx"); #endif @@ -913,7 +913,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return posi; @@ -959,7 +959,7 @@ static Word16 imax_fx( /* o: The location, relative to the Word16 P_in_plocs; Word16 n_real_interp_tail; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::spec_ana_fx(1st)"); #endif #ifdef DYNMEM_COUNT @@ -1008,7 +1008,7 @@ static Word16 imax_fx( /* o: The location, relative to the rectLength = sub(Lprot, shl_pos(hamm_len2, 1)); /* The length of the rectangular portion of the Hamming-Rectangular window. */ { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::WhrAnaWin+fft"); #endif @@ -1016,7 +1016,7 @@ static Word16 imax_fx( /* o: The location, relative to the windowing_L(xfp, L_xfp, sp_ana_win, rectLength, hamm_len2); BASOP_rfftN(L_xfp, Lprot, &fft_scale, buffer_fft); } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); /* anawin+fft */ #endif @@ -1035,7 +1035,7 @@ static Word16 imax_fx( /* o: The location, relative to the basop_memset(xfp + stop_band_start, 0, (stop_band_length) * sizeof(Word16)); } - peak_range_1 = s_min(Lprot2p1, MAX_LPROT_RED / 2 + 1); /* limit preliminary only active for 48k to save WMOPS */ + peak_range_1 = s_min(Lprot2p1, MAX_LPROT_RED / 2 + 1); /* limit preliminary only active for 48k to save WMOPS_LC3PLUS */ basop_memmove(X_sav, xfp, (Lprot) * sizeof(Word16)); @@ -1052,7 +1052,7 @@ static Word16 imax_fx( /* o: The location, relative to the plc_phEcu_peak_locator_fx(xfp, peak_range_1, plocs, num_plocs, sens, Xmax, Xmin, MAX_LPROT_RED, buffer_fft); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::Peaks_refine"); #endif @@ -1173,7 +1173,7 @@ static Word16 imax_fx( /* o: The location, relative to the } } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); /* peaks refine */ #endif @@ -1217,7 +1217,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -1307,13 +1307,13 @@ static Word16 imax_fx( /* o: The location, relative to the if (time_offs == 0) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::subst_spec_fx(1st)"); #endif } else { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::subst_spec_fx(N)"); #endif } @@ -1669,7 +1669,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -1700,7 +1700,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::my_wtda_fx"); #endif @@ -1760,7 +1760,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return; @@ -1807,7 +1807,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::rec_wtda_fx"); #endif @@ -1849,7 +1849,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif @@ -1893,7 +1893,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::rec_frame_fx"); #endif @@ -1912,11 +1912,11 @@ static Word16 imax_fx( /* o: The location, relative to the fft_scale = -1; move16(); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::IFFT_fx"); #endif BASOP_irfftN(L_x, Lprot, &fft_scale, buffer_fft); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif @@ -1955,7 +1955,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return; @@ -2036,13 +2036,13 @@ static Word16 imax_fx( /* o: The location, relative to the if (!prev_bfi) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::hq_phase_ecu_fx(1st)"); #endif } else { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::hq_phase_ecu_fx(N)"); #endif } @@ -2244,7 +2244,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -2256,7 +2256,7 @@ static Word16 imax_fx( /* o: The location, relative to the { Word32 acc; Word16 z; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::sqrt2ndOrder"); #endif @@ -2268,7 +2268,7 @@ static Word16 imax_fx( /* o: The location, relative to the z = mac_r(acc, z, x); /* in Q15 */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return z; @@ -2297,7 +2297,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::windowing_L"); #endif @@ -2335,7 +2335,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -2359,7 +2359,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::windowing_ola"); #endif @@ -2375,7 +2375,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -2460,7 +2460,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::sqrtMagnApprox_fx"); #endif @@ -2478,7 +2478,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return sum; @@ -2520,7 +2520,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::fft_spec2_sqrt_approx_fx"); #endif @@ -2547,7 +2547,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return; @@ -2584,7 +2584,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::imax2_jacobsen_mag_fx"); #endif @@ -2667,7 +2667,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif return posi; /* Q15. The position either left or right relative to the index of the middle of the 3 given @@ -2692,7 +2692,7 @@ static Word16 imax_fx( /* o: The location, relative to the #define FHG_FFT_UPSHIFT 2 -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::intlvW32_2_flippedW16"); #endif #ifdef DYNMEM_COUNT @@ -2750,7 +2750,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -2766,7 +2766,7 @@ static Word16 imax_fx( /* o: The location, relative to the Counter numPairsLocal; Word32 *pX_L; Word16 *pX_re, *pX_im; -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::flippedW16_2_intlvW32"); #endif #ifdef DYNMEM_COUNT @@ -2802,7 +2802,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -2818,7 +2818,7 @@ static Word16 imax_fx( /* o: The location, relative to the Dyn_Mem_In("get_sin_cosQ10", sizeof(struct { Word16 sign_val, idx, idx2, idx3; })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::get_sin_cosQ10opt"); #endif @@ -2871,7 +2871,7 @@ static Word16 imax_fx( /* o: The location, relative to the #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } @@ -2902,7 +2902,7 @@ static Word16 imax_fx( /* o: The location, relative to the })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhEcu::nonpure_tone_ana_fx"); #endif @@ -3144,7 +3144,7 @@ static Word16 imax_fx( /* o: The location, relative to the } /* bands available*/ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif diff --git a/lib_lc3plus/plc_phecu_peak_locator_fx.c b/lib_lc3plus/plc_phecu_peak_locator_fx.c index 531ee8f6f..78a6ec281 100644 --- a/lib_lc3plus/plc_phecu_peak_locator_fx.c +++ b/lib_lc3plus/plc_phecu_peak_locator_fx.c @@ -65,7 +65,7 @@ void plc_phEcu_peak_locator_fx(const Word16 *inp, /* i: vector with values >=0 Word16 *fsc_idx; })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::peak_locator_fx(1st)"); #endif sc_idx = (Word16 *)scratchAlign(scratchBuffer, 0); /* ByteSize = 2 * (1+ inp_len+1) */ @@ -378,7 +378,7 @@ void plc_phEcu_peak_locator_fx(const Word16 *inp, /* i: vector with values >=0 #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif } diff --git a/lib_lc3plus/plc_phecu_setf0hz_fx.c b/lib_lc3plus/plc_phecu_setf0hz_fx.c index 6fffe632c..264aa19c3 100644 --- a/lib_lc3plus/plc_phecu_setf0hz_fx.c +++ b/lib_lc3plus/plc_phecu_setf0hz_fx.c @@ -32,7 +32,7 @@ plc_phEcuSetF0Hz_fx(/* output Q7 bin frequency [0.. 255.xxxx] "1 sign, 8 bits })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::plc_phEcuSetF0Hz_fx"); #endif @@ -50,7 +50,7 @@ plc_phEcuSetF0Hz_fx(/* output Q7 bin frequency [0.. 255.xxxx] "1 sign, 8 bits #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif diff --git a/lib_lc3plus/plc_phecu_tools_fx.c b/lib_lc3plus/plc_phecu_tools_fx.c index 13e90fa49..32eff68f2 100644 --- a/lib_lc3plus/plc_phecu_tools_fx.c +++ b/lib_lc3plus/plc_phecu_tools_fx.c @@ -91,7 +91,7 @@ Word16 plc_phEcu_find_ind_fx( /* o : output maximum in const Word16 *inp, /* i : vector */ const Word16 len, /* i : length */ const Word16 val /* i : value to find */ -) +) { Word16 val_ind; Counter pos; @@ -149,37 +149,37 @@ Word32 winEnCalc( /* o: output summed energy Ltot */ const Word16 *win, /* i: left side Window coefficients */ const Word16 rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */ const Word16 halfLength, /* i: Half of the total length of a complete Hamming window. */ - Word16 *exp /* i/o : i exp of Word16 variable x , o:Lexp of output Word32 sum */ + Word16 *exp /* i/o : i exp of Word16 variable x , o:Lexp of output Word32 sum */ ) { Counter i; - Word32 L_tot; + Word32 L_tot; const Word16 *pX, *pW; Word16 tmp, tmp_RL; #ifdef DYNMEM_COUNT Dyn_Mem_In("PhEcu::GF::winEnCalc", sizeof(struct { Counter i; - Word32 L_tot; + Word32 L_tot; const Word16 *pX, *pW; Word16 tmp, tmp_RL; })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::winEnCalc"); #endif L_tot = INT32_MAX; move32(); /*acc is on negative side , but as all accumulation is positive, we make use of one extra bit */ pX = x; pW = win; - + assert( headroom_shift>=0 ); FOR (i = 0; i < halfLength; i++) /* 1st symmetric half of the Hamming window */ { - tmp = mult(*pX++, *pW++); + tmp = mult(*pX++, *pW++); tmp = shr_pos(tmp, headroom_shift); /* shr may/create bias on the negative side , costly options are shr_r or use msu_r */ L_tot = L_msu0(L_tot, tmp, tmp); /* acc on negative energy side */ } @@ -189,7 +189,7 @@ Word32 winEnCalc( /* o: output summed energy Ltot */ ASSERT(rectLength != 0); FOR (i = 0; i < tmp_RL; i++) /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */ - { + { tmp = shr_pos( *pX++, headroom_shift); L_tot = L_msu0(L_tot, tmp, tmp); /* acc on negative side */ } @@ -199,49 +199,49 @@ Word32 winEnCalc( /* o: output summed energy Ltot */ FOR (i = 0; i < tmp_RL; i++) /* 2nd symmetric half of the Hamming window. */ { - tmp = mult(*pX++, *(--pW)); + tmp = mult(*pX++, *(--pW)); tmp = shr_pos(tmp, headroom_shift); L_tot = L_msu0(L_tot, tmp, tmp); } /* Lexp = 2*(incoming_exp + dnshift) + 1 , 2x for square + 1(for msu0 DSP dn shift)*/ - *exp = add(shl_pos(add(*exp, headroom_shift),1),1); + *exp = add(shl_pos(add(*exp, headroom_shift),1),1); /* handle wrap on zero point */ IF( L_tot >= 0 ) { /* L_tot positive --> less than 32 bits needed, */ L_tot = L_add(L_tot,(INT32_MIN+1)); if( L_tot == 0 ) - { + { *exp = LTOT_MIN_EXP; /* WC is actually (-(15+4)*2 + 1 +1 -31) */ ; move16(); - } + } L_tot = L_min(L_tot, -1); /* make sure there is energy for future ratio calculations */ - } - ELSE + } + ELSE { /* L_tot negative --> more than 31 bits needed for sum , scale 32 bit sum within 31 bits and adjust exp */ - + L_tot = L_shr_pos(L_add(L_tot,1),1); /* rnd by adding 1, then use 50% contribution from negative side */ - L_tot = L_add(L_tot, INT32_MIN>>1); /* add 50% contribution from positive side */ - - *exp = add(*exp, 1); move16(); - } + L_tot = L_add(L_tot, INT32_MIN>>1); /* add 50% contribution from positive side */ + + *exp = add(*exp, 1); move16(); + } L_tot = L_max( -(INT32_MAX), L_tot); /* guard against max accumulation on the negative side , should only occur for rectangle windows */ L_tot = L_negate(L_tot); /* no saturation here */ - /* activate when xfp_exp is not used any longer */ + /* activate when xfp_exp is not used any longer */ /* pre-maximize the mantissa for the following steps in burst_ana_dx */ tmp = norm_l(L_tot); L_tot = L_shl(L_tot,tmp); *exp = sub(*exp, tmp); move16(); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif #ifdef DYNMEM_COUNT Dyn_Mem_Out(); #endif - + return L_tot; } diff --git a/lib_lc3plus/plc_update_aft_imdct_fx.c b/lib_lc3plus/plc_update_aft_imdct_fx.c index 663f491c9..6be74bb61 100644 --- a/lib_lc3plus/plc_update_aft_imdct_fx.c +++ b/lib_lc3plus/plc_update_aft_imdct_fx.c @@ -36,12 +36,12 @@ void processPLCUpdateAfterIMDCT_fx(Word16 x_fx[], Word16 q_fx_exp, Word16 concea - -#ifdef WMOPS + +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("processPLCUpdateAfterIMDCT "); #endif - - + + if (plcAd) { /* for short NB frames(2.5 ms) TDC-filtering requires more PCM samples than the plc_xcorr function */ @@ -78,7 +78,7 @@ void processPLCUpdateAfterIMDCT_fx(Word16 x_fx[], Word16 q_fx_exp, Word16 concea marginOldFront = getScaleFactor16_0(&(plcAd->x_old_tot_fx[plcAd->max_len_pcm_plc - usedHistlen + pastLen]), frontLen); scale_fac_old = s_min(marginOldFront, marginOldPast); - + frontLen = 0; move16(); logic16(); logic16(); IF(bfi == 1 && *prev_bfi == 0 && sub(concealMethod, LC3_CON_TEC_PHASE_ECU) == 0) @@ -155,12 +155,12 @@ void processPLCUpdateAfterIMDCT_fx(Word16 x_fx[], Word16 q_fx_exp, Word16 concea plcAd->PhECU_short_flag_prev = 0; move16(); /* fullband transient not active */ } } - + /* values may be {0,1,2} */ *prev_prev_bfi = *prev_bfi; move16(); *prev_bfi = bfi; move16(); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif @@ -233,28 +233,28 @@ static void processPLCcomputeStabFac(Word16 scf_q[], Word16 old_scf_q[], Word16 #endif } -void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, Word16 *xfp_fx, Word16 xfp_exp_fx, Word16 margin_xfp, +void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, Word16 *xfp_fx, Word16 xfp_exp_fx, Word16 margin_xfp, Word16 fs_idx, - Word32 *L_oold_xfp_w_E_fx, Word16 *oold_xfp_w_E_exp_fx, + Word32 *L_oold_xfp_w_E_fx, Word16 *oold_xfp_w_E_exp_fx, Word32 *L_old_xfp_w_E_fx, Word16 *old_xfp_w_E_exp_fx, - - Word16 *oold_Ltot_exp_fx ,Word16 *old_Ltot_exp_fx ) + + Word16 *oold_Ltot_exp_fx ,Word16 *old_Ltot_exp_fx ) { - Word32 L_tot ; + Word32 L_tot ; Word16 dn_scale, exp_shift; Word16 used_xfp_exp_fx; - Word16 exp_out ; + Word16 exp_out ; #ifdef DYNMEM_COUNT - Dyn_Mem_In("PLCUpdateXFP_w_E_hist", sizeof(struct { + Dyn_Mem_In("PLCUpdateXFP_w_E_hist", sizeof(struct { Word32 L_tot; Word16 dn_scale, exp_shift; Word16 used_xfp_exp_fx; - Word16 exp_out; + Word16 exp_out; })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::UpdateXfp_w_E_hist_fx"); #endif @@ -263,16 +263,16 @@ void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, Word16 *xfp_fx if (sub(prev_bfi,1) == 0) { - /* only a single historic frame available in the next frame + /* only a single historic frame available in the next frame , force artifical update of oold energy to be the same as old */ *old_xfp_w_E_exp_fx = LTOT_INIT_FLAG ; move16(); } - /* Time shift energy state and xfp exp */ - IF (sub_sat(*old_xfp_w_E_exp_fx, LTOT_INIT_FLAG ) == 0) + /* Time shift energy state and xfp exp */ + IF (sub_sat(*old_xfp_w_E_exp_fx, LTOT_INIT_FLAG ) == 0) { - *L_oold_xfp_w_E_fx = LTOT_MIN_MAN ; move32(); - *oold_xfp_w_E_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL ; move16(); + *L_oold_xfp_w_E_fx = LTOT_MIN_MAN ; move32(); + *oold_xfp_w_E_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL ; move16(); } ELSE { @@ -281,10 +281,10 @@ void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, Word16 *xfp_fx } /* Time shift L_tot energy state and L_tot_exp */ - IF (sub_sat(*old_Ltot_exp_fx, LTOT_INIT_FLAG ) == 0) + IF (sub_sat(*old_Ltot_exp_fx, LTOT_INIT_FLAG ) == 0) { - *L_oold_xfp_w_E_fx = LTOT_MIN_MAN ; move32(); - *oold_Ltot_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL ; move16(); + *L_oold_xfp_w_E_fx = LTOT_MIN_MAN ; move32(); + *oold_Ltot_exp_fx = UNINIT_OR_UNSAFE_OOLD_SENTINEL ; move16(); } ELSE { @@ -292,46 +292,46 @@ void processPLCUpdateXFP_w_E_hist_fx(Word16 prev_bfi, Word16 bfi, Word16 *xfp_fx *oold_Ltot_exp_fx = *old_Ltot_exp_fx; move16(); } - + dn_scale = e_tot_headroom[fs_idx]; /* allowed minimum dn_scale for a max upshifted signal */ - used_xfp_exp_fx = xfp_exp_fx; - + used_xfp_exp_fx = xfp_exp_fx; + IF( margin_xfp > 0 ) /* xfp_fx was normalized on a larger area than 16ms part of pcmBuffer */ - { + { ASSERT(bfi !=1) ; /* if bfi was set the margin_xfp does not reflect the correct 16ms part of pcm_buf hist, prev_synth */ - dn_scale = s_max(0, sub(e_tot_headroom[fs_idx], margin_xfp)); + dn_scale = s_max(0, sub(e_tot_headroom[fs_idx], margin_xfp)); exp_shift = sub(e_tot_headroom[fs_idx], dn_scale); used_xfp_exp_fx = sub(xfp_exp_fx, exp_shift); /* the virtual change of the xfp_buffer due to reduced downscaling in L_tot calc */ } - + /* use semifixed dn_scale as adjusted by margin_xfp in 16 ms region */ exp_out = xfp_exp_fx; move16(); L_tot = winEnCalc(xfp_fx, dn_scale , PhECU_wins[fs_idx][0], rectLengthTab[fs_idx], hamm_len2Tab[fs_idx], &exp_out ); - + *L_old_xfp_w_E_fx = L_tot; move32(); - *old_xfp_w_E_exp_fx = used_xfp_exp_fx ; move16(); + *old_xfp_w_E_exp_fx = used_xfp_exp_fx ; move16(); /* this now needs to be in Q1 , used_fx_exp , (exp_out-1-2*e_tot_headroom[fs_idx])/2 */ - *old_Ltot_exp_fx = exp_out; /* new proper _Ltot value from winEnCalc function */ + *old_Ltot_exp_fx = exp_out; /* new proper _Ltot value from winEnCalc function */ + - /* use true Word32 exponent of L_tot */ - - /* restart oold and old from same state for init or prevBFI cases */ + + /* restart oold and old from same state for init or prevBFI cases */ logic16(); IF (sub_sat(*oold_xfp_w_E_exp_fx, UNINIT_OR_UNSAFE_OOLD_SENTINEL) <= 0 || /* old xfp_Exp */ sub_sat(*oold_Ltot_exp_fx, UNINIT_OR_UNSAFE_OOLD_SENTINEL) <= 0 ) /* new L_tot_exp */ { *L_oold_xfp_w_E_fx = L_tot; move32(); - *oold_xfp_w_E_exp_fx = used_xfp_exp_fx; move16(); - *oold_Ltot_exp_fx = *old_Ltot_exp_fx; /* use Ltot exp value */ + *oold_xfp_w_E_exp_fx = used_xfp_exp_fx; move16(); + *oold_Ltot_exp_fx = *old_Ltot_exp_fx; /* use Ltot exp value */ } } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif #ifdef DYNMEM_COUNT diff --git a/lib_lc3plus/plc_update_fx.c b/lib_lc3plus/plc_update_fx.c index fb05770d5..b219aa674 100644 --- a/lib_lc3plus/plc_update_fx.c +++ b/lib_lc3plus/plc_update_fx.c @@ -22,10 +22,10 @@ void processPLCupdate_fx(AplcSetup *plcAd, Word16 x_fx[], Word16 q_fx_exp, Word1 scf_q, ns_cum_alpha, plcAd); /* NB *prev_bfi updated here */ IF ( plcAd != 0 ) - { + { /* reuse/inplace the most recent 16 ms of x_old_tot without additional rescaling, keep exponent aligned with tdc pitch buffer to save WMOPS */ - + #ifdef ENABLE_HR_MODE if (hrmode == 0) #endif @@ -57,14 +57,14 @@ void processPLCupdateSpec_fx(Word16 q_old_d_fx[], Word16 *q_old_fx_exp, Word32 q Dyn_Mem_Deluxe_Out(); } -void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], Word16 yLen, +void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], Word16 yLen, Word16 *stPhECU_oold_grp_shape_fx, Word16 *stPhECU_old_grp_shape_fx) -#define L_GRP_DC 4 +#define L_GRP_DC 4 { - Counter i,l; - Word16 *pX, tmp; + Counter i,l; + Word16 *pX, tmp; Word16 N_grp,l_grp; Word16 man, expo; Word32 L_acc; @@ -72,12 +72,12 @@ void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], W Word32 L_grp_shape[MAX_LGW]; Word16 grp_shape[MAX_LGW]; /**/ Word16 fs_idx,local_prev_bfi; - + #ifdef DYNMEM_COUNT Dyn_Mem_In("process_plc_spec_2_shape_fx", sizeof(struct { Counter i,l; - Word16 *pX; + Word16 *pX; Word16 N_grp,l_grp; Word32 L_acc; Word32 L_tot; @@ -85,7 +85,7 @@ void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], W Word16 fs_idx,local_prev_bfi; })); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("PhECU::GF::process_plc_spec_2_shape_fx"); #endif @@ -95,77 +95,77 @@ void processPLCspec2shape_fx(Word16 prev_bfi, Word16 bfi, Word16 q_old_d_fx[], W N_grp = xavg_N_grp_fx[fs_idx]; move16(); local_prev_bfi = prev_bfi; move16(); - if (sub(local_prev_bfi, 2)==0) + if (sub(local_prev_bfi, 2)==0) { local_prev_bfi = 0; move16(); } - if( stPhECU_oold_grp_shape_fx[0] < 0 ) + if( stPhECU_oold_grp_shape_fx[0] < 0 ) { - local_prev_bfi = 1 ; move16(); /* handle startup in the case 2nd frame is a BFI frame */ + local_prev_bfi = 1 ; move16(); /* handle startup in the case 2nd frame is a BFI frame */ } /* Copy old to oold grp shape */ - FOR( i=0; i < MAX_LGW ; i++) + FOR( i=0; i < MAX_LGW ; i++) { stPhECU_oold_grp_shape_fx[i] = stPhECU_old_grp_shape_fx[i]; move16(); - } - - + } + + /* Accumulate DC bin(s) to total */ - pX = q_old_d_fx; /* ptr setup */ + pX = q_old_d_fx; /* ptr setup */ L_tot = L_deposit_h(0); /* acc on negative side */ - + FOR( i= 0; i < L_GRP_DC; i++) { tmp = shr_pos(*pX++ ,spec_shape_headroom[fs_idx]); /* scale down upscaled MDCT to create some headroom */ - L_tot = L_msu0(L_tot, tmp, tmp); - + L_tot = L_msu0(L_tot, tmp, tmp); + } - + /* Accumulate middle subbands and add to total */ FOR( i=0; i < sub(N_grp,1) ; i++) { - + L_acc = L_deposit_h(0); /* acc on negative side */ l_grp = sub(mdct_grp_bins_fx[i+1], mdct_grp_bins_fx[i]); move16(); - + FOR(l=0;l= 0 && idx < R); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif #ifdef DYNMEM_COUNT @@ -183,7 +183,7 @@ static void processQuantize_stage1ScfEncStage1_fx(const Word16 *target_st1, Word16 *st1_idx0Ptr, Word16 *st1_idx1Ptr) { -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("processQuantize_stage1ScfEncStage1_fx"); #endif @@ -201,7 +201,7 @@ static void processQuantize_stage1ScfEncStage1_fx(const Word16 *target_st1, *st1_idx1Ptr, st1_vector); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif @@ -306,7 +306,7 @@ static void pvq_enc_find_best_submode_pre_post_fx( shape_far = (Word16 *)scratchAlign(pulses_far, sizeof(*pulses_far) * M); /* Size = 2 * M */ #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("pvq_enc_find_best_submode_pre_post_fx"); #endif @@ -414,7 +414,7 @@ static void pvq_enc_find_best_submode_pre_post_fx( *sub_mode_ptr = extract_l(L_section); move16(); /* 0,1,2,3 */ -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif #ifdef DYNMEM_COUNT @@ -505,7 +505,7 @@ static void processQuantize_stage2ScfEncStage2_fx( proc_target_lp = (Word16 *)buffer_pvq_enc_find_best_submode_pre_post_fx; /* size = 2*M */ #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("processQuantize_stage2ScfEncStage2_fx"); #endif @@ -631,7 +631,7 @@ static void processQuantize_stage2ScfEncStage2_fx( L_prm_idx[2] = L_deposit_l(enc_PVQ_OA.lead_sign_ind); /* LS shape single bit */ } -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif #ifdef DYNMEM_COUNT @@ -676,7 +676,7 @@ static Word16 scfdec_stage2_fx( /* o: ber flag */ ); #endif -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_start("scfdec_stage2_fx"); #endif @@ -740,7 +740,7 @@ static Word16 scfdec_stage2_fx( /* o: ber flag */ /* scaling aligend with encoder search */ pvq_dec_scale_vec_fx(dec_adj_glob_vec, gValQ13, st2_vector); -#ifdef WMOPS +#ifdef WMOPS_LC3PLUS BASOP_sub_sub_end(); #endif Dyn_Mem_Deluxe_Out(); -- GitLab From 480eae02f1a8c25a2d2c4a5fb5a61051b98f9b2a Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 6 Feb 2025 13:45:17 +1100 Subject: [PATCH 22/43] another attempt to resolve lc3plus intrumentation erros, fix for SBA pytests --- lib_dec/ivas_binRenderer_internal.c | 33 +++++++++++++++++++++++------ lib_lc3plus/defines.h | 1 - lib_lc3plus/setup_dec_lc3.h | 18 ++++++++-------- lib_lc3plus/setup_enc_lc3.h | 20 ++++++++--------- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index c31f0cbf7..70f8219f9 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -554,16 +554,35 @@ static ivas_error ivas_binRenderer_convModuleOpen( } #ifdef SPLIT_REND_WITH_HEAD_ROT - for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + IF( EQ_16( renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) { - for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) { - for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) + for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) { - /* set the memories to zero */ - set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); - set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); - set16_fx( hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx][chIdx], 31, hBinRenConvModule->numTaps ); + for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) + { + /* set the memories to zero */ + set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); + set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTapsArray[bandIdx] ); + set16_fx( hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx][chIdx], 31, hBinRenConvModule->numTapsArray[bandIdx] ); + } + } + } + } + ELSE + { + for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ ) + { + for ( bandIdx = 0; bandIdx < hBinRenderer->conv_band; bandIdx++ ) + { + for ( chIdx = 0; chIdx < hBinRenderer->nInChannels; chIdx++ ) + { + /* set the memories to zero */ + set32_fx( hBinRenConvModule->filterStatesLeftReal_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTaps ); + set32_fx( hBinRenConvModule->filterStatesLeftImag_fx[pos_idx][bandIdx][chIdx], 0, hBinRenConvModule->numTaps ); + set16_fx( hBinRenConvModule->Q_filterStatesLeft[pos_idx][bandIdx][chIdx], 31, hBinRenConvModule->numTaps ); + } } } } diff --git a/lib_lc3plus/defines.h b/lib_lc3plus/defines.h index ebf538b71..2d280620f 100644 --- a/lib_lc3plus/defines.h +++ b/lib_lc3plus/defines.h @@ -725,7 +725,6 @@ do not change __forceinline for mex compilation using gcc6.3.0 or larger #endif #define scratchAlign(ptr, offset) (void *)(((uintptr_t)(ptr) + (offset) + 0x3) & ~0x3) -#define ALIGN_BUFFER_STRUCT /* some configurations leave empty translation units. */ diff --git a/lib_lc3plus/setup_dec_lc3.h b/lib_lc3plus/setup_dec_lc3.h index 5c36163d3..3145cd21c 100644 --- a/lib_lc3plus/setup_dec_lc3.h +++ b/lib_lc3plus/setup_dec_lc3.h @@ -28,9 +28,9 @@ typedef struct Word16 tdc_preemph_fac; Word16 tdc_lpc_order; Word16 cum_fflcAtten; - Word16 harmonicBuf_fx[MAX_PITCH] ALIGN_BUFFER_STRUCT; + Word16 harmonicBuf_fx[MAX_PITCH]; Word16 harmonicBuf_Q; - Word16 synthHist_fx[M] ALIGN_BUFFER_STRUCT; + Word16 synthHist_fx[M]; Word16 cum_fading_slow; Word16 cum_fading_fast; Word16 PhECU_LprotOrg_fx; /* needed to change the Prot size adaptively */ @@ -63,17 +63,17 @@ typedef struct Word32 PhECU_L_old_xfp_w_E_fx; Word16 PhECU_oold_xfp_w_E_exp_fx; /* input Word16 xfp exponnet */ Word16 PhECU_old_xfp_w_E_exp_fx; - Word16 PhECU_oold_grp_shape_fx[MAX_LGW] ALIGN_BUFFER_STRUCT; - Word16 PhECU_old_grp_shape_fx[MAX_LGW] ALIGN_BUFFER_STRUCT; + Word16 PhECU_oold_grp_shape_fx[MAX_LGW]; + Word16 PhECU_old_grp_shape_fx[MAX_LGW]; Word16 PhECU_margin_xfp; #ifdef CR8_A_PLC_FADEOUT_TUNING Word16 PhECU_nonpure_tone_flag; /* non-pure single tone indicator state */ #endif - Word16 PhECU_mag_chg_1st[MAX_LGW] ALIGN_BUFFER_STRUCT; - Word16 PhECU_Xavg[MAX_LGW] ALIGN_BUFFER_STRUCT; - Word16 old_scf_q[M] ALIGN_BUFFER_STRUCT; - Word16 old_old_scf_q[M] ALIGN_BUFFER_STRUCT; - Word16 tdc_A[M + 1] ALIGN_BUFFER_STRUCT; + Word16 PhECU_mag_chg_1st[MAX_LGW]; + Word16 PhECU_Xavg[MAX_LGW]; + Word16 old_scf_q[M]; + Word16 old_old_scf_q[M]; + Word16 tdc_A[M + 1]; /* for now 20 ms saved Q14 or ptr to a combined ifft win and MDCT preTDA synthesis window 16 ms */ #ifdef CR8_A_PLC_FADEOUT_TUNING diff --git a/lib_lc3plus/setup_enc_lc3.h b/lib_lc3plus/setup_enc_lc3.h index 5e89829da..34e26a59d 100644 --- a/lib_lc3plus/setup_enc_lc3.h +++ b/lib_lc3plus/setup_enc_lc3.h @@ -53,24 +53,24 @@ typedef struct Word16 attdec_scaling; #ifdef ENABLE_HR_MODE Word16 regBits; - Word32 resamp_mem32[120] ALIGN_BUFFER_STRUCT; + Word32 resamp_mem32[120]; #else - Word32 resamp_mem32[60] ALIGN_BUFFER_STRUCT; + Word32 resamp_mem32[60]; #endif #ifdef ENABLE_HR_MODE - Word16 r12k8_mem_in[120] ALIGN_BUFFER_STRUCT; + Word16 r12k8_mem_in[120]; #else - Word16 r12k8_mem_in[60] ALIGN_BUFFER_STRUCT; + Word16 r12k8_mem_in[60]; #endif - Word32 r12k8_mem_50[2] ALIGN_BUFFER_STRUCT; + Word32 r12k8_mem_50[2]; #ifdef CR8_G_ADD_75MS - Word16 r12k8_mem_out[44] ALIGN_BUFFER_STRUCT; + Word16 r12k8_mem_out[44]; #else - Word16 r12k8_mem_out[24] ALIGN_BUFFER_STRUCT; + Word16 r12k8_mem_out[24]; #endif - Word16 olpa_mem_s12k8[3] ALIGN_BUFFER_STRUCT; - Word16 olpa_mem_s6k4[LEN_6K4 + MAX_PITCH_6K4 + 16] ALIGN_BUFFER_STRUCT; - Word16 ltpf_mem_in[LTPF_MEMIN_LEN + LEN_12K8 + 1] ALIGN_BUFFER_STRUCT; + Word16 olpa_mem_s12k8[3]; + Word16 olpa_mem_s6k4[LEN_6K4 + MAX_PITCH_6K4 + 16]; + Word16 ltpf_mem_in[LTPF_MEMIN_LEN + LEN_12K8 + 1]; Word16 n_pccw; Word16 n_pc; -- GitLab From 4811ef2a2d9e80d59b78e064f8414adc4b746b89 Mon Sep 17 00:00:00 2001 From: rtyag Date: Mon, 10 Feb 2025 18:06:53 +1100 Subject: [PATCH 23/43] masa renderer test failures fixes --- lib_rend/ivas_dirac_dec_binaural_functions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 3e5bb8b86..ea975dfbe 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -6658,7 +6658,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe, subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp ); ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe, - hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, + hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL ); #endif -- GitLab From 70147babc4843b0ec44beaf043d09e1258f1ee89 Mon Sep 17 00:00:00 2001 From: rtyag Date: Tue, 11 Feb 2025 17:27:59 +1100 Subject: [PATCH 24/43] missing renderer config changes --- lib_util/render_config_reader.c | 145 +++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/lib_util/render_config_reader.c b/lib_util/render_config_reader.c index 692f8c58d..dd8c36492 100644 --- a/lib_util/render_config_reader.c +++ b/lib_util/render_config_reader.c @@ -1069,7 +1069,11 @@ static void strip_spaces( while ( pStr[read_idx] ) { +#ifdef SPLIT_REND_WITH_HEAD_ROT + if ( !isspace( (int32_t) pStr[read_idx] ) && !iscntrl( (int32_t) pStr[read_idx] ) ) +#else if ( !isspace( pStr[read_idx] ) && !iscntrl( pStr[read_idx] ) ) +#endif { pStr[write_idx++] = pStr[read_idx]; } @@ -1833,6 +1837,10 @@ ivas_error RenderConfigReader_read( uint32_t fgHasMethod, fgHasNBands, fgHasFreqs, fgHasDefaultGrid, fgHasStartFreq, fgHasFreqHop; uint32_t aeHasFgIdx, aeHasPredelay, aeHasRt60, aeHasDsr; uint32_t aeHasERsize, aeHasERabs; +#ifdef SPLIT_REND_WITH_HEAD_ROT + bool dofProvided = false; + bool poseCorrProvided = false; +#endif uint32_t nDP; uint32_t accDPIdx; @@ -2349,7 +2357,142 @@ ivas_error RenderConfigReader_read( free( pValue ); acIdx++; } - +#ifdef SPLIT_REND_WITH_HEAD_ROT + else if ( strcmp( chapter, "SPLITREND" ) == 0 && strlen( pParams ) != 0 ) + { + params_idx = 0; + pValue = (char *) calloc( strlen( pParams ), sizeof( char ) ); + while ( sscanf( pParams + params_idx, "%64[^=]=%[^;];", item, pValue ) == 2 ) + { + params_idx += (int32_t) ( strlen( item ) + strlen( pValue ) + 2 ); +#ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG + fprintf( stderr, " PARAM: %s -> %s\n", item, pValue ); +#endif + if ( strcmp( item, "CODECDELAY" ) == 0 ) + { + if ( !sscanf( pValue, "%hd", &hRenderConfig->split_rend_config.codec_delay_ms ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } + else if ( strcmp( item, "HQMODE" ) == 0 ) + { + if ( !sscanf( pValue, "%hd", &hRenderConfig->split_rend_config.hq_mode ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } + else if ( strcmp( item, "BITRATE" ) == 0 ) + { + if ( !sscanf( pValue, "%d", &hRenderConfig->split_rend_config.splitRendBitRate ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } + else if ( strcmp( item, "DOF" ) == 0 ) + { + dofProvided = true; + if ( !sscanf( pValue, "%hd", &hRenderConfig->split_rend_config.dof ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + /* 0 DOF implies no pose correction */ + if ( hRenderConfig->split_rend_config.dof == 0 && !poseCorrProvided ) + { + hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + } + } + else if ( strcmp( item, "CODEC" ) == 0 ) + { + if ( strcmp( pValue, "LCLD" ) == 0 ) + { + hRenderConfig->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_LCLD; + } + else if ( strcmp( pValue, "LC3PLUS" ) == 0 ) + { + hRenderConfig->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_LC3PLUS; + } + else + { + errorHandler( pValue, ERROR_VALUE_INVALID ); + } + } + else if ( strcmp( item, "FRAMESIZE" ) == 0 ) + { + if ( !sscanf( pValue, "%hd", &hRenderConfig->split_rend_config.codec_frame_size_ms ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + if ( hRenderConfig->split_rend_config.codec_frame_size_ms != 5 && + hRenderConfig->split_rend_config.codec_frame_size_ms != 10 && + hRenderConfig->split_rend_config.codec_frame_size_ms != 20 ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } + else if ( strcmp( item, "POSECORRECTION" ) == 0 ) + { + poseCorrProvided = true; + if ( strcmp( pValue, "CLDFB" ) == 0 ) + { + hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB; + } + else if ( strcmp( pValue, "NONE" ) == 0 ) + { + hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + /* no pose correction implies 0 DOF */ + if ( !dofProvided ) + { + hRenderConfig->split_rend_config.dof = 0; + } + } + else + { + errorHandler( pValue, ERROR_VALUE_INVALID ); + } + } + else if ( strcmp( item, "RENDERER" ) == 0 ) + { + if ( strcmp( pValue, "CREND" ) == 0 ) + { + hRenderConfig->split_rend_config.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_CREND; + } + else if ( strcmp( pValue, "FASTCONV" ) == 0 ) + { + hRenderConfig->split_rend_config.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV; + } + else if ( strcmp( pValue, "PARAMBIN" ) == 0 ) + { + hRenderConfig->split_rend_config.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_PARAMBIN; + } + else if ( strcmp( pValue, "TDREND" ) == 0 ) + { + hRenderConfig->split_rend_config.rendererSelection = ISAR_SPLIT_REND_RENDERER_SELECTION_TDREND; + } + else + { + errorHandler( pValue, ERROR_VALUE_INVALID ); + } + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + else if ( strcmp( item, "LC3PLUS_HIGHRES" ) == 0 ) + { + if ( !sscanf( pValue, "%hd", &hRenderConfig->split_rend_config.lc3plus_highres ) ) + { + errorHandler( item, ERROR_VALUE_INVALID ); + } + } +#endif +#ifdef DEBUGGING + else + { + fprintf( stderr, "Unsupported configuration property %s\n", item ); + } +#endif + } + free( pValue ); + } +#endif else if ( strcmp( chapter, "DIRECTIVITYSETTING" ) == 0 && strlen( pParams ) != 0 ) { params_idx = 0; -- GitLab From 64ac4f93dd1e6b2f09b7906ab661c4cba4643e88 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 11 Feb 2025 09:12:26 +0100 Subject: [PATCH 25/43] Add -p BASOP for build-codec-linux-instrumented-make --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4fe5ec338..16563bf57 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -896,7 +896,7 @@ build-codec-linux-instrumented-make: script: - *print-common-info - *update-scripts-repo - - bash scripts/prepare_instrumentation.sh -m MEM_ONLY + - bash scripts/prepare_instrumentation.sh -m MEM_ONLY -p BASOP - make -j -C $INSTR_DIR -- GitLab From 4b2c1d98dae4a80ce82a23cad1d86064869f5ede Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 11 Feb 2025 18:10:20 +0100 Subject: [PATCH 26/43] Revert call to prepare_instrumentation.sh --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 16563bf57..4fe5ec338 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -896,7 +896,7 @@ build-codec-linux-instrumented-make: script: - *print-common-info - *update-scripts-repo - - bash scripts/prepare_instrumentation.sh -m MEM_ONLY -p BASOP + - bash scripts/prepare_instrumentation.sh -m MEM_ONLY - make -j -C $INSTR_DIR -- GitLab From 76dc2a8289c4b66c902c2f0a05bc8a2bb8922c13 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 12 Feb 2025 17:06:31 +1100 Subject: [PATCH 27/43] fixes to pre renderer and post renderer --- lib_com/ivas_rotation_com.c | 8 ++++---- lib_dec/ivas_binRenderer_internal.c | 30 ++++++++++++++--------------- lib_dec/lib_dec_fx.c | 10 +++++----- lib_isar/isar_PredEncoder.c | 4 ++-- lib_isar/isar_splitRendererPost.c | 11 ++++++++--- lib_isar/isar_splitRendererPre.c | 5 +++-- lib_isar/lib_isar_post_rend.c | 3 ++- lib_isar/lib_isar_pre_rend.c | 4 ++-- lib_rend/lib_rend.c | 6 +++--- 9 files changed, 43 insertions(+), 38 deletions(-) diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index fccc5498b..b48fdfec2 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -57,12 +57,12 @@ void Euler2Quat_fx( IVAS_QUATERNION *quat /* o : quaternion describing the rotation Q22*/ ) { - Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) ); // Q14 - Word16 sr = getSinWord16( extract_l( L_shr_r( roll, 10 ) ) ); + Word16 cr = getCosWord16( extract_l( L_shr_r( roll, 10 ) ) ); // Q14 + Word16 sr = shr( getSinWord16( extract_l( L_shr_r( roll, 10 ) ) ), 1 ); // Q14 Word16 cp = getCosWord16( extract_l( L_shr_r( pitch, 10 ) ) ); - Word16 sp = getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ); + Word16 sp = shr( getSinWord16( extract_l( L_shr_r( pitch, 10 ) ) ), 1 ); // Q14 Word16 cy = getCosWord16( extract_l( L_shr_r( yaw, 10 ) ) ); - Word16 sy = getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ); + Word16 sy = shr( getSinWord16( extract_l( L_shr_r( yaw, 10 ) ) ), 1 ); // Q14 quat->w_fx = L_shr_r( L_add( Mpy_32_16_1( L_mult0( cr, cp ), cy ), Mpy_32_16_1( L_mult0( sr, sp ), sy ) ), 5 ); // Q22 move32(); quat->x_fx = L_shr_r( L_sub( Mpy_32_16_1( L_mult0( sr, cp ), cy ), Mpy_32_16_1( L_mult0( cr, sp ), sy ) ), 5 ); // Q22 diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 70f8219f9..f0cda2bca 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1955,30 +1955,29 @@ void ivas_binRenderer_fx( { IF( GT_16( pMultiBinPoseData->num_poses, 1 ) ) { - IVAS_QUATERNION Quaternions_rel, Quaternions_abs, *Quaternions_ref; + IVAS_QUATERNION Quaternions_abs, Quaternions_ref, Quaternions_ref2; Word32 Rmat_local[MAX_PARAM_SPATIAL_SUBFRAMES][3][3]; Word16 q_fact_orig; IF( hCombinedOrientationData && hBinRenderer->rotInCldfb ) { - Quaternions_ref = &hCombinedOrientationData->Quaternions[0]; - Quaternions_rel.w_fx = L_negate( 12582912 ); // Q22 - Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 - q_fact_orig = Quaternions_ref->q_fact; + Quaternions_ref = hCombinedOrientationData->Quaternions[0]; + q_fact_orig = Quaternions_ref.q_fact; - modify_Quat_q_fx( Quaternions_ref, Quaternions_ref, Q22 ); + modify_Quat_q_fx( &Quaternions_ref, &Quaternions_ref, Q22 ); + Quaternions_ref2.w_fx = L_negate( 12582912 ); // Q22 IF( EQ_16( hCombinedOrientationData->shd_rot_max_order, 0 ) ) { /*HOA signal already rotated by DirAC*/ - Quaternions_abs.x_fx = 0; - Quaternions_abs.y_fx = 0; - Quaternions_abs.z_fx = 0; + Quaternions_ref2.x_fx = 0; + Quaternions_ref2.y_fx = 0; + Quaternions_ref2.z_fx = 0; } ELSE { /*euler*/ - Quat2EulerDegree_fx( *Quaternions_ref, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + Quat2EulerDegree_fx( Quaternions_ref, &Quaternions_ref2.z_fx, &Quaternions_ref2.y_fx, &Quaternions_ref2.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ } FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) @@ -1991,12 +1990,11 @@ void ivas_binRenderer_fx( Copy32( ImagBuffer_local[chIdx][k], ImagBuffer_fx[chIdx][k], CLDFB_NO_CHANNELS_MAX ); } } - Quaternions_rel.x_fx = L_sub( pMultiBinPoseData->relative_head_poses_fx[pos_idx][0], pMultiBinPoseData->relative_head_poses_fx[pos_idx - 1][0] ); - Quaternions_rel.y_fx = L_sub( pMultiBinPoseData->relative_head_poses_fx[pos_idx][1], pMultiBinPoseData->relative_head_poses_fx[pos_idx - 1][1] ); - Quaternions_rel.z_fx = L_sub( pMultiBinPoseData->relative_head_poses_fx[pos_idx][2], pMultiBinPoseData->relative_head_poses_fx[pos_idx - 1][2] ); - Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, Quaternions_rel.x_fx ); - Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, Quaternions_rel.y_fx ); - Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, Quaternions_rel.z_fx ); + + Quaternions_abs.x_fx = L_add( Quaternions_ref2.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] ); + Quaternions_abs.y_fx = L_add( Quaternions_ref2.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] ); + Quaternions_abs.z_fx = L_add( Quaternions_ref2.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] ); + Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), deg2rad_fx( Quaternions_abs.y_fx ), deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs ); diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 2e6085494..9917b6f40 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -1493,7 +1493,7 @@ IVAS_DEC_GetSplitBinauralBitstream( Q_out[0] = 31; Word16 num_poses = hSplitBinRend->splitrend.multiBinPoseData.num_poses; - for ( i = 0; i < 16; i++ ) + for ( i = 0; i < i_mult( BINAURAL_CHANNELS, numPoses ); i++ ) { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { @@ -1502,12 +1502,12 @@ IVAS_DEC_GetSplitBinauralBitstream( } } Q_buff = s_min( q1, q2 ); - for ( i = 0; i < 16; i++ ) + for ( i = 0; i < i_mult( BINAURAL_CHANNELS, numPoses ); i++ ) { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - scale_sig32( Cldfb_RealBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); - scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + scale_sig32( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); + scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); } } Q_buff = Q_buff + Q6; @@ -1526,7 +1526,7 @@ IVAS_DEC_GetSplitBinauralBitstream( FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { - scale_sig32( output[i], Q_out[0], L_FRAME48k ); + scale_sig32( output[i], L_FRAME48k, Q_out[0] ); } } if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hSplitBinRend->splitrend, diff --git a/lib_isar/isar_PredEncoder.c b/lib_isar/isar_PredEncoder.c index d2b6e0f5c..0fb2c05a5 100644 --- a/lib_isar/isar_PredEncoder.c +++ b/lib_isar/isar_PredEncoder.c @@ -999,7 +999,7 @@ void ComputePredictors_fx( iA1Mag = ( iA1Mag > PRED_QUANT_FILTER_MAG_MIN ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MIN; iA1Mag = ( iA1Mag < PRED_QUANT_FILTER_MAG_MAX ) ? iA1Mag : PRED_QUANT_FILTER_MAG_MAX; // fA1Mag = sinf(fInvMagScale * (float)iA1Mag); - fA1Mag_fx = L_deposit_l( getSinWord16( extract_l( L_shr( L_mult0( extract_l( fInvMagScale_fx ), extract_l( iA1Mag ) ), 2 ) ) ) ); // Q14 + fA1Mag_fx = L_deposit_l( shr( getSinWord16( extract_l( L_shr( L_mult0( extract_l( fInvMagScale_fx ), extract_l( iA1Mag ) ), 2 ) ) ), 1 ) ); // Q14 // fA1Phase = atan2f(fA1Imag, fA1Real); fA1Phase_fx = BASOP_util_atan2( fA1Imag_fx, fA1Real_fx, 0 ); // Q13 @@ -1025,7 +1025,7 @@ void ComputePredictors_fx( // fA1Real = fA1Mag * cosf(fA1Phase); fA1Real_fx = L_mult0( extract_l( fA1Mag_fx ), getCosWord16( extract_l( L_shr( L_temp, 2 ) ) ) ); // Q28 // fA1Imag = fA1Mag * sinf(fA1Phase); - fA1Imag_fx = L_mult0( extract_l( fA1Mag_fx ), getSinWord16( extract_l( L_shr( L_temp, 2 ) ) ) ); // Q28 + fA1Imag_fx = L_mult0( extract_l( fA1Mag_fx ), shr( getSinWord16( extract_l( L_shr( L_temp, 2 ) ) ), 1 ) ); // Q28 // fGain2 = 1.0f / (1.0f - fA1Real * fA1Real - fA1Imag * fA1Imag); exp = 0; diff --git a/lib_isar/isar_splitRendererPost.c b/lib_isar/isar_splitRendererPost.c index c313e9ca4..82ac5558d 100644 --- a/lib_isar/isar_splitRendererPost.c +++ b/lib_isar/isar_splitRendererPost.c @@ -858,6 +858,9 @@ void isar_splitBinPostRendMdDec_fx( angle = sub( angle, 180 ); hBinHrSplitPostRend->QuaternionsPre[sf_idx].z_fx = L_shl( angle, Q22 ); /* Q22 */ move32(); + + hBinHrSplitPostRend->QuaternionsPre[sf_idx].q_fact = Q22; + move32(); } #ifdef SPLIT_REND_POSE_CORRECTION_UNUSED_BITS @@ -1347,7 +1350,7 @@ static void get_interpolation_vars( Word16 *q_pitch, Word16 *q_roll ) { - IVAS_QUATERNION quaternions_diff, quaternions_ref_euler, quaternions_act_euler; + IVAS_QUATERNION quaternions_diff, quaternions_ref_euler, quaternions_act_euler, quaternions_ref_q22, quaternions_act_q22; Word32 y_fx[MAX_HEAD_ROT_POSES], p_fx[MAX_HEAD_ROT_POSES], r_fx[MAX_HEAD_ROT_POSES]; int16_t pos_idx, num_poses; @@ -1371,8 +1374,10 @@ static void get_interpolation_vars( /*interpolation if actual pose is not same as one of assumed poses*/ /*get the deviation*/ - Quat2EulerDegree_fx( *Quaternions_ref, &quaternions_ref_euler.z_fx, &quaternions_ref_euler.y_fx, &quaternions_ref_euler.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ - Quat2EulerDegree_fx( *Quaternions_act, &quaternions_act_euler.z_fx, &quaternions_act_euler.y_fx, &quaternions_act_euler.x_fx ); + modify_Quat_q_fx( Quaternions_ref, &quaternions_ref_q22, Q22 ); + modify_Quat_q_fx( Quaternions_act, &quaternions_act_q22, Q22 ); + Quat2EulerDegree_fx( quaternions_ref_q22, &quaternions_ref_euler.z_fx, &quaternions_ref_euler.y_fx, &quaternions_ref_euler.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ + Quat2EulerDegree_fx( quaternions_act_q22, &quaternions_act_euler.z_fx, &quaternions_act_euler.y_fx, &quaternions_act_euler.x_fx ); /*order in Quat2Euler seems to be reversed ?*/ quaternions_diff.w_fx = -12582912; /*euler*/ //-3 in Q22 diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 092358962..bf60095cb 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -2130,9 +2130,10 @@ static void isar_SplitRenderer_quant_code( FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { Word16 angle; - IVAS_QUATERNION head_pos_euler; + IVAS_QUATERNION head_pos_euler, headPosition_q22; - Quat2EulerDegree_fx( headPosition, &head_pos_euler.z_fx, &head_pos_euler.y_fx, &head_pos_euler.x_fx ); + modify_Quat_q_fx( &headPosition, &headPosition_q22, Q22 ); + Quat2EulerDegree_fx( headPosition_q22, &head_pos_euler.z_fx, &head_pos_euler.y_fx, &head_pos_euler.x_fx ); angle = (Word16) L_shr_r( head_pos_euler.x_fx, Q22 ); angle = add( angle, 180 ); ISAR_SPLIT_REND_BITStream_write_int32( pBits, angle, ISAR_SPLIT_REND_HEAD_POSE_BITS ); diff --git a/lib_isar/lib_isar_post_rend.c b/lib_isar/lib_isar_post_rend.c index 768b23089..c59159061 100644 --- a/lib_isar/lib_isar_post_rend.c +++ b/lib_isar/lib_isar_post_rend.c @@ -1268,9 +1268,10 @@ ivas_error ISAR_POST_REND_SetHeadRotation( hIvasRend->headRotData.headRotEnabled = 1; /* check for Euler angle signaling */ - IF( EQ_32( headRot.w_fx, -12582912 ) ) + IF( EQ_32( headRot.w_fx, -12582912 ) && EQ_32( headRot.q_fact, Q22 ) ) { Euler2Quat_fx( deg2rad_fx( headRot.x_fx ), deg2rad_fx( headRot.y_fx ), deg2rad_fx( headRot.z_fx ), &rotQuat ); + modify_Quat_q_fx( &rotQuat, &rotQuat, Q29 ); } ELSE { diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index bafb68a15..f528d0348 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -402,7 +402,7 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Word16 Q_Cldfb_re = 31, Q_Cldfb_im = 31; move16(); move16(); - FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + FOR( i = 0; i < hSplitBin->multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ ) { FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { @@ -410,7 +410,7 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( Q_Cldfb_im = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[i][j], CLDFB_NO_CHANNELS_MAX ), Q_Cldfb_im ); } } - FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + FOR( i = 0; i < hSplitBin->multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ ) { FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index bacdec5d1..87afb721c 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -8962,8 +8962,8 @@ static ivas_error getSamplesInternal( { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - scale_sig32( Cldfb_RealBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); - scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], Q_buff, CLDFB_NO_CHANNELS_MAX ); + scale_sig32( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); + scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); } } Q_buff = Q_buff + Q6; @@ -8980,7 +8980,7 @@ static ivas_error getSamplesInternal( FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { - scale_sig32( tmpBinaural_buff[i], Q_out[0], L_FRAME48k ); + scale_sig32( tmpBinaural_buff[i], L_FRAME48k, Q_out[0] ); } Q_out[0] = Q_out[0] + *outAudio.pq_fact; -- GitLab From 40b6e9836cbf04043fc209993844af4569ce76af Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 13 Feb 2025 14:36:53 +1100 Subject: [PATCH 28/43] fixes to MASA and ISM split pre-renderer --- lib_dec/ivas_objectRenderer_internal.c | 13 +- lib_rend/ivas_dirac_dec_binaural_functions.c | 123 +++++++++++-------- 2 files changed, 81 insertions(+), 55 deletions(-) diff --git a/lib_dec/ivas_objectRenderer_internal.c b/lib_dec/ivas_objectRenderer_internal.c index 8a73539be..4c0b92888 100644 --- a/lib_dec/ivas_objectRenderer_internal.c +++ b/lib_dec/ivas_objectRenderer_internal.c @@ -366,6 +366,7 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( Word16 original_slots_rendered; Word32 *p_bin_output[BINAURAL_CHANNELS]; Word32 output_local[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + Word16 q_fact_orig[MAX_PARAM_SPATIAL_SUBFRAMES]; Word16 SrcInd[MAX_NUM_TDREND_CHANNELS]; @@ -399,6 +400,7 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) { originalHeadRot[i] = st_ivas->hCombinedOrientationData->Quaternions[i]; + q_fact_orig[i] = originalHeadRot[i].q_fact; } original_subframes_rendered = st_ivas->hTcBuffer->subframes_rendered; @@ -408,18 +410,20 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( origTdRendHandle = st_ivas->hBinRendererTd; move32(); + FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) + { + modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 ); + } + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { /* Update head positions */ IF( NE_16( pos_idx, 0 ) ) { COMBINED_ORIENTATION_HANDLE pCombinedOrientationData = st_ivas->hCombinedOrientationData; - Word16 q_fact_orig; FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) { pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22 - q_fact_orig = originalHeadRot[i].q_fact; - modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 ); /*euler*/ Quat2EulerDegree_fx( originalHeadRot[i], &pCombinedOrientationData->Quaternions[i].z_fx, @@ -433,7 +437,7 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( deg2rad_fx( pCombinedOrientationData->Quaternions[i].y_fx ), deg2rad_fx( pCombinedOrientationData->Quaternions[i].z_fx ), &pCombinedOrientationData->Quaternions[i] ); - modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig ); + modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig[i] ); } } @@ -482,6 +486,7 @@ ivas_error ivas_td_binaural_renderer_sf_splitBinaural( /* Restore original head rotation */ FOR( i = 0; i < st_ivas->hCombinedOrientationData->num_subframes; ++i ) { + modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], q_fact_orig[i] ); st_ivas->hCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; move32(); } diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index ea975dfbe..0d6673fa8 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -123,7 +123,7 @@ static void ivas_dirac_dec_binaural_formulate_input_and_target_covariance_matric static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, Word32 Rmat[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData ); #ifdef SPLIT_REND_WITH_HEAD_ROT -static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat, Word32 outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word8 recompute ); +static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat, Word32 outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 *Q_inp_mix, const Word8 recompute ); #else static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat ); #endif @@ -694,6 +694,7 @@ static void ivas_dirac_dec_binaural_internal_fx( Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX]; Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX]; Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 Q_inp_mix; hDiracDecBin = st_ivas->hDiracDecBin[0]; #else @@ -1116,7 +1117,7 @@ static void ivas_dirac_dec_binaural_internal_fx( #endif { ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, - tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 ); FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { @@ -1130,7 +1131,7 @@ static void ivas_dirac_dec_binaural_internal_fx( ELSE { ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL, - reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 ); } #else ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); @@ -1162,6 +1163,7 @@ static void ivas_dirac_dec_binaural_internal_fx( move32(); move32(); move32(); + Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot ); modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact ); QuatToRotMat_fx( Quaternions_rot, Rmat_local ); @@ -1173,12 +1175,15 @@ static void ivas_dirac_dec_binaural_internal_fx( } /* re-use input covariance for the side renderings */ - for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { Copy32( st_ivas->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands ); + Copy( st_ivas->hDiracDecBin[0]->ChEne_e[ch], hDiracDecBin->ChEne_e[ch], hSpatParamRendCom->num_freq_bands ); } Copy32( st_ivas->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands ); Copy32( st_ivas->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands ); + Copy( st_ivas->hDiracDecBin[0]->ChCrossRe_e, hDiracDecBin->ChCrossRe_e, hSpatParamRendCom->num_freq_bands ); + Copy( st_ivas->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands ); ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, @@ -1227,7 +1232,7 @@ static void ivas_dirac_dec_binaural_internal_fx( /* re-use reverb and decorr from main direction for the sides */ ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, - tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 0 ); + tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 0 ); /* copy from temporary buffer to the main split rendering buffer */ FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) @@ -3399,6 +3404,7 @@ static void ivas_dirac_dec_binaural_process_output_fx( Word32 reverbIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], + Word16 *Q_inp_mix, const Word8 recompute #endif ) @@ -3442,69 +3448,82 @@ static void ivas_dirac_dec_binaural_process_output_fx( #endif } - // scaling input and reverb to same q// - // input scaling is to maintain precision in ivas_dirac_dec_decorrelate_slot fn// - Word16 shift = s_min( L_norm_arr( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length ), L_norm_arr( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length ) ); - q_inp_mix = 31; - move16(); - FOR( Word16 i = 0; i < 6; i++ ) +#ifdef SPLIT_REND_WITH_HEAD_ROT + IF( EQ_16( recompute, 1 ) ) { - FOR( Word16 j = 0; j < nSlots; j++ ) +#endif + // scaling input and reverb to same q// + // input scaling is to maintain precision in ivas_dirac_dec_decorrelate_slot fn// + Word16 shift = s_min( L_norm_arr( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length ), L_norm_arr( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length ) ); + q_inp_mix = 31; + move16(); + FOR( Word16 i = 0; i < 6; i++ ) { - q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); - move16(); - test(); + FOR( Word16 j = 0; j < nSlots; j++ ) + { + q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) ); + move16(); + test(); #ifdef SPLIT_REND_WITH_HEAD_ROT - IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) ) + IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) ) #else IF( ( processReverb ) && LT_16( i, 2 ) ) #endif - { - q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) ); - q_inp[i][j] = s_min( q_reverb, q_inp[i][j] ); - move16(); + { + q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) ); + q_inp[i][j] = s_min( q_reverb, q_inp[i][j] ); + move16(); + } + q_inp_mix = s_min( q_inp[i][j], q_inp_mix ); } - q_inp_mix = s_min( q_inp[i][j], q_inp_mix ); } - } - q_inp_mix = sub( q_inp_mix, 3 ); // gaurded bits// + q_inp_mix = sub( q_inp_mix, 3 ); // gaurded bits// - Word16 cldfb_state_shift = sub( add( add( q_inp_mix, q_mat ), sub( q_input, 16 ) ), cldfbSynDec[0]->Q_cldfb_state ); - IF( GT_16( cldfb_state_shift, shift ) ) - { - q_inp_mix = sub( add( q_inp_mix, shift ), cldfb_state_shift ); - cldfb_state_shift = shift; - move16(); - } + Word16 cldfb_state_shift = sub( add( add( q_inp_mix, q_mat ), sub( q_input, 16 ) ), cldfbSynDec[0]->Q_cldfb_state ); + IF( GT_16( cldfb_state_shift, shift ) ) + { + q_inp_mix = sub( add( q_inp_mix, shift ), cldfb_state_shift ); + cldfb_state_shift = shift; + move16(); + } - FOR( Word16 i = 0; i < 6; i++ ) - { - FOR( Word16 j = 0; j < nSlots; j++ ) + FOR( Word16 i = 0; i < 6; i++ ) { + FOR( Word16 j = 0; j < nSlots; j++ ) + { - scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ - scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ - test(); + scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ + scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/ + test(); #ifdef SPLIT_REND_WITH_HEAD_ROT - IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) ) + IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) ) #else IF( ( processReverb ) && LT_16( i, 2 ) ) #endif - { - scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ - scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ + { + scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ + scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, sub( add( q_inp_mix, q_mat ), 15 ) ); /*q_inp_mix+q_mat-15*/ + } } } - } - // scaling cldfb states to q_result-1// - scale_sig32( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length, cldfb_state_shift ); - cldfbSynDec[0]->Q_cldfb_state = add( cldfbSynDec[0]->Q_cldfb_state, cldfb_state_shift ); - scale_sig32( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length, cldfb_state_shift ); - cldfbSynDec[1]->Q_cldfb_state = add( cldfbSynDec[1]->Q_cldfb_state, cldfb_state_shift ); - move16(); - move16(); + // scaling cldfb states to q_result-1// + scale_sig32( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length, cldfb_state_shift ); + cldfbSynDec[0]->Q_cldfb_state = add( cldfbSynDec[0]->Q_cldfb_state, cldfb_state_shift ); + scale_sig32( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length, cldfb_state_shift ); + cldfbSynDec[1]->Q_cldfb_state = add( cldfbSynDec[1]->Q_cldfb_state, cldfb_state_shift ); + move16(); + move16(); +#ifdef SPLIT_REND_WITH_HEAD_ROT + *Q_inp_mix = q_inp_mix; + move16(); + } + ELSE + { + q_inp_mix = *Q_inp_mix; + } +#endif q_inp_mix = add( q_inp_mix, q_input ); @@ -6511,6 +6530,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX]; Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX]; Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX]; + Word16 Q_inp_mix; hDiracDecBin = hMasaExtRend->hDiracDecBin[0]; #else @@ -6718,7 +6738,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData ); ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im, - reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 ); for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { @@ -6732,7 +6752,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( else { ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL, - reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 1 ); + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 ); } #else ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat ); @@ -6765,6 +6785,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( move32(); move32(); move32(); + Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot ); modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact ); QuatToRotMat_fx( Quaternions_rot, Rmat_local ); @@ -6824,7 +6845,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( move16(); /* re-use reverb and decorr from main direction for the sides */ ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im, - reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, 0 ); + reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 0 ); /* copy from temporary buffer to the main split rendering buffer */ for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) -- GitLab From 71d8bfca7aa86fa27d812fdecb0bb0b452cb6154 Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 13 Feb 2025 15:42:40 +1100 Subject: [PATCH 29/43] fixes to MC crend --- lib_rend/ivas_crend.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index faf696393..a974364f4 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -2686,6 +2686,10 @@ ivas_error ivas_rend_crendProcessSubframesSplitBin( move32(); move32(); move32(); + Euler2Quat_fx( deg2rad_fx( combinedOrientationDataLocal.Quaternions[i].x_fx ), + deg2rad_fx( combinedOrientationDataLocal.Quaternions[i].y_fx ), + deg2rad_fx( combinedOrientationDataLocal.Quaternions[i].z_fx ), + &combinedOrientationDataLocal.Quaternions[i] ); modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Quaternions_orig[i].q_fact ); QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); } -- GitLab From 2e7c1ae960402cda3f53da9dd2a47e5251eb931e Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 13 Feb 2025 18:08:18 +1100 Subject: [PATCH 30/43] fixes in OSBA and OMASA --- lib_dec/ivas_omasa_dec.c | 10 +++++++++- lib_dec/ivas_osba_dec.c | 9 ++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index 0079ae4de..bce96994d 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -808,7 +808,7 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( Word32 Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX]; Word32 *p_rend_obj[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; /* [8 * 2] */ - Word16 q_cldfb = 11; + Word16 q_cldfb, q_in = 11; move16(); FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); n++ ) @@ -834,10 +834,18 @@ ivas_error ivas_omasa_dirac_td_binaural_jbm_fx( FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); ++n ) { + q_cldfb = q_in; + Scale_sig32( st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->cldfb_state_fx, + sub( st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->p_filter_length, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->no_channels ), + sub( q_cldfb, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->Q_cldfb_state ) ); + st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->Q_cldfb_state = q_cldfb; FOR( slot_idx = 0; slot_idx < cldfb_slots; slot_idx++ ) { + q_cldfb = q_in; cldfbAnalysis_ts_fx_fixed_q( &( p_rend_obj[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb ); + Scale_sig32( Cldfb_RealBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); + Scale_sig32( Cldfb_ImagBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); /* note: this intentionally differs from OSBA by: no scaling by 0.5 */ v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_RealBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands ); v_add_fx( st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], Cldfb_ImagBuffer, st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[n][slot_idx_start + slot_idx], num_cldfb_bands ); diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index 1c008caa0..47288e820 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -167,7 +167,7 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( Word16 cldfb_slots; Word32 Cldfb_RealBuffer[CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer[CLDFB_NO_CHANNELS_MAX]; - Word16 q_cldfb = 11; + Word16 q_cldfb, q_in = 11; move16(); num_cldfb_bands = st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[0]->no_channels; @@ -186,11 +186,18 @@ ivas_error ivas_osba_dirac_td_binaural_jbm_fx( FOR( n = 0; n < i_mult( st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses, BINAURAL_CHANNELS ); ++n ) { + q_cldfb = q_in; + Scale_sig32( st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->cldfb_state_fx, + sub( st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->p_filter_length, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->no_channels ), + sub( q_cldfb, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->Q_cldfb_state ) ); + st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n]->Q_cldfb_state = q_cldfb; FOR( slot_idx = 0; slot_idx < cldfb_slots; slot_idx++ ) { + q_cldfb = q_in; cldfbAnalysis_ts_fx_fixed_q( &( output_fx[n][num_cldfb_bands * slot_idx] ), Cldfb_RealBuffer, Cldfb_ImagBuffer, num_cldfb_bands, st_ivas->hSplitBinRend->splitrend.hCldfbHandles->cldfbAna[n], &q_cldfb ); Scale_sig32( Cldfb_RealBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); + Scale_sig32( Cldfb_ImagBuffer, num_cldfb_bands, sub( Q6, q_cldfb ) ); FOR( b = 0; b < num_cldfb_bands; b++ ) { st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[n][slot_idx_start + slot_idx][b] = -- GitLab From e731929cc029b67ec24b93c80ae3fedaa284ff82 Mon Sep 17 00:00:00 2001 From: rtyag Date: Fri, 14 Feb 2025 19:47:48 +1100 Subject: [PATCH 31/43] fixes in external renderer --- apps/renderer.c | 1 + lib_dec/ivas_binRenderer_internal.c | 7 ++-- lib_rend/ivas_dirac_dec_binaural_functions.c | 3 ++ lib_rend/lib_rend.c | 40 +++++++++++++++----- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 6f55853d6..3537e7c25 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -53,6 +53,7 @@ #include "wmc_auto.h" #include "prot_fx.h" +#include "debug.h" #define WMC_TOOL_SKIP diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index f0cda2bca..97d7905f3 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1228,7 +1228,7 @@ ivas_error ivas_rend_openCldfbRend( } /* Allocate memories and buffers needed for convolutional module in CICP19 */ - IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, RENDERER_BINAURAL_FASTCONV, 1, inConfig, pCldfbRend->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) ) + IF( NE_32( ( error = ivas_binRenderer_convModuleOpen( hBinRenderer, RENDERER_BINAURAL_FASTCONV, hBinRenderer->hInputSetup->is_loudspeaker_setup, inConfig, pCldfbRend->hHrtfFastConv, hBinRenderer->numPoses ) ), IVAS_ERR_OK ) ) { return error; } @@ -2127,11 +2127,12 @@ void ivas_rend_CldfbMultiBinRendProcess( Word32 Cldfb_ImagBuffer_sfIn[MAX_INPUT_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][MAX_PARAM_SPATIAL_SUBFRAMES][CLDFB_NO_CHANNELS_MAX]; - Word16 Q_in_orig = Q_in; - move16(); + Word16 Q_in_orig; FOR( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { + Q_in_orig = Q_in; + move16(); FOR( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) { idx = sf_idx * MAX_PARAM_SPATIAL_SUBFRAMES + slot_idx; diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 0d6673fa8..04964dfec 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -6796,9 +6796,12 @@ static void ivas_masa_ext_rend_parambin_internal_fx( FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { Copy32( hMasaExtRend->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands ); + Copy( hMasaExtRend->hDiracDecBin[0]->ChEne_e[ch], hDiracDecBin->ChEne_e[ch], hSpatParamRendCom->num_freq_bands ); } Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands ); Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands ); + Copy( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_e, hDiracDecBin->ChCrossRe_e, hSpatParamRendCom->num_freq_bands ); + Copy( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands ); ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0, diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 87afb721c..1432c1eac 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -398,7 +398,7 @@ static void copyBufferToCLDFBarray_fx( assert( ( buffer.config.is_cldfb == 1 ) && "for time domain input call copyBufferTo2dArray()" ); readPtr = buffer.data_fx; - numCldfbSamples = (UWord32) shl( buffer.config.numSamplesPerChannel, 1 ); + numCldfbSamples = (UWord32) shr( buffer.config.numSamplesPerChannel, 1 ); num_bands = (UWord32) Mpy_32_32( numCldfbSamples, ONE_BY_CLDFB_NO_COL_MAX_Q31 ); FOR( chnlIdx = 0; chnlIdx < (UWord32) buffer.config.numChannels; ++chnlIdx ) { @@ -430,7 +430,7 @@ static void accumulateCLDFBArrayToBuffer_fx( assert( ( buffer->config.is_cldfb == 1 ) && "for time domain input call copyBufferTo2dArray()" ); writePtr = buffer->data_fx; - numCldfbSamples = (UWord32) shl( buffer->config.numSamplesPerChannel, 1 ); + numCldfbSamples = (UWord32) shr( buffer->config.numSamplesPerChannel, 1 ); num_bands = (UWord32) Mpy_32_32( numCldfbSamples, ONE_BY_CLDFB_NO_COL_MAX_Q31 ); FOR( chnlIdx = 0; chnlIdx < (uint32_t) buffer->config.numChannels; ++chnlIdx ) { @@ -3924,6 +3924,9 @@ static ivas_error ivas_pre_rend_init( { return IVAS_ERR_FAILED_ALLOC; } + + pSplitRendEncBuffer->q_factor = 0; + pSplitRendEncBuffer->pq_fact = &pSplitRendEncBuffer->q_factor; } ELSE { @@ -3934,6 +3937,8 @@ static ivas_error ivas_pre_rend_init( bufConfig2.is_cldfb = 0; pSplitRendEncBuffer->config = bufConfig2; pSplitRendEncBuffer->data_fx = NULL; + pSplitRendEncBuffer->pq_fact = NULL; + pSplitRendEncBuffer->q_factor = 0; move16(); move16(); move16(); @@ -4937,11 +4942,20 @@ ivas_error IVAS_REND_SetHeadRotation( } } +#ifdef SPLIT_REND_WITH_HEAD_ROT + /* check for Euler angle signaling */ + IF( EQ_32( headRot.w_fx, L_negate( 12582912 ) ) && EQ_16( headRot.q_fact, Q22 ) ) + { + Euler2Quat_fx( deg2rad_fx( headRot.x_fx ), deg2rad_fx( headRot.y_fx ), deg2rad_fx( headRot.z_fx ), &rotQuat ); + modify_Quat_q_fx( &rotQuat, &rotQuat, Q29 ); + } +#else /* check for Euler angle signaling */ IF( EQ_32( headRot.w_fx, -1610612736 /* -3.0f in Q29 */ ) ) { Euler2Quat_fx( deg2rad_fx( headRot.x_fx ), deg2rad_fx( headRot.y_fx ), deg2rad_fx( headRot.z_fx ), &rotQuat ); } +#endif ELSE { rotQuat = headRot; @@ -6254,6 +6268,7 @@ static ivas_error renderIsmToSplitBinaural( const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; const SPLIT_REND_WRAPPER *pSplitRendWrapper; IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; + IVAS_QUATERNION localHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; Word16 i; Word32 tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; Word16 output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; @@ -6299,9 +6314,9 @@ static ivas_error renderIsmToSplitBinaural( { pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22 q_fact_orig = originalHeadRot[i].q_fact; - modify_Quat_q_fx( &originalHeadRot[i], &originalHeadRot[i], Q22 ); + modify_Quat_q_fx( &originalHeadRot[i], &localHeadRot[i], Q22 ); /*euler*/ - Quat2EulerDegree_fx( originalHeadRot[i], + Quat2EulerDegree_fx( localHeadRot[i], &pCombinedOrientationData->Quaternions[i].z_fx, &pCombinedOrientationData->Quaternions[i].y_fx, &pCombinedOrientationData->Quaternions[i].x_fx ); @@ -7571,6 +7586,9 @@ static ivas_error renderSbaToMultiBinaural( IF( NE_32( ( error = ivas_rend_crendProcess( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, *sbaInput->base.ctx.pOutSampleRate, getNumSubframesInBuffer( &tmpRotBuffer, *sbaInput->base.ctx.pOutSampleRate ), pos_idx ) ), IVAS_ERR_OK ) ) + { + return error; + } FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) { @@ -8850,7 +8868,8 @@ static ivas_error getSamplesInternal( Word16 num_poses_orig; num_poses_orig = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; move16(); - outAudio = hIvasRend->splitRendEncBuffer; + outAudio.config = hIvasRend->splitRendEncBuffer.config; + outAudio.data_fx = hIvasRend->splitRendEncBuffer.data_fx; ISAR_PRE_REND_GetMultiBinPoseData( &hIvasRend->hRendererConfig->split_rend_config, &hIvasRend->splitRendWrapper.multiBinPoseData, hIvasRend->headRotData.sr_pose_pred_axis ); @@ -8949,7 +8968,7 @@ static ivas_error getSamplesInternal( Q_out[0] = 31; Word16 num_poses = hIvasRend->splitRendWrapper.multiBinPoseData.num_poses; - for ( i = 0; i < 16; i++ ) + for ( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ ) { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { @@ -8958,7 +8977,7 @@ static ivas_error getSamplesInternal( } } Q_buff = s_min( q1, q2 ); - for ( i = 0; i < 16; i++ ) + for ( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ ) { for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { @@ -8966,7 +8985,7 @@ static ivas_error getSamplesInternal( scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); } } - Q_buff = Q_buff + Q6; + Q_buff = Q_buff + *outAudio.pq_fact; IF( EQ_16( cldfb_in_flag, 0 ) ) { @@ -9008,7 +9027,8 @@ static ivas_error getSamplesInternal( convertInternalBitsBuffToBitsBuffer( hBits, bits ); /* reset to outAudioOrig in case of PCM output */ - outAudio = outAudioOrig; + outAudio.config = outAudioOrig.config; + outAudio.data_fx = outAudioOrig.data_fx; IF( NE_16( pcm_out_flag, 0 ) ) { @@ -9272,8 +9292,10 @@ void IVAS_REND_cldfbAnalysis_ts_wrapper( { Word16 Q_cldfb = Q_in; + assert( Q_in == h_cldfb->Q_cldfb_state ); cldfbAnalysis_ts_fx_fixed_q( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb, &Q_cldfb ); + *Q_out = sub( Q_in, 5 ); return; -- GitLab From 923d397d3ac1f3dd98ce019e34d3bca222908d04 Mon Sep 17 00:00:00 2001 From: rtyag Date: Sat, 15 Feb 2025 00:53:26 +1100 Subject: [PATCH 32/43] q factor fix with TD in to pre renderer --- lib_isar/isar_splitRendererPre.c | 12 +++++------- lib_rend/lib_rend.c | 13 ++++++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index bf60095cb..306753bd6 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -3129,8 +3129,6 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( Word16 Q_in = Q_sig, q_final = 0; move16(); move16(); - // float Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - // float Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; UWord8 useLc3plus; Word32 *in_delayed_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS]; Word16 i; @@ -3154,12 +3152,11 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( { /* Artificially delay input to head pose correction analysis by LC3plus coding delay, so that audio and metadata are in sync after decoding */ mvl2l( hSplitBin->lc3plusDelayBuffers_fx[i] + frame_size, hSplitBin->lc3plusDelayBuffers_fx[i], (Word16) hSplitBin->lc3plusDelaySamples ); - // mvr2r( hSplitBin->lc3plusDelayBuffers[i] + frame_size, hSplitBin->lc3plusDelayBuffers[i], (int16_t) hSplitBin->lc3plusDelaySamples ); in_delayed_fx[i] = hSplitBin->lc3plusDelayBuffers_fx[i]; - // in_delayed[i] = hSplitBin->lc3plusDelayBuffers[i]; + Scale_sig32( hSplitBin->lc3plusDelayBuffers_fx[i], (Word16) hSplitBin->lc3plusDelaySamples, sub( Q_in, hSplitBin->lc3plusDelayBuffers_q ) ); mvl2l( in_fx[i], hSplitBin->lc3plusDelayBuffers_fx[i] + hSplitBin->lc3plusDelaySamples, frame_size ); - // mvr2r(in[i], hSplitBin->lc3plusDelayBuffers[i] + hSplitBin->lc3plusDelaySamples, frame_size); } + hSplitBin->lc3plusDelayBuffers_q = Q_in; } ELSE { @@ -3180,12 +3177,13 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( IF( ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) || ( !useLc3plus && !pcm_out_flag ) ) { Word32 in_delayed_cldfb[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k] = { 0 }; + Word16 gd_bits = sub( Q_sig, Q11 ); FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ ) { Copy32( in_delayed_fx[i], in_delayed_cldfb[i], L_FRAME48k ); - Scale_sig32( in_delayed_cldfb[i], L_FRAME48k, -4 ); + Scale_sig32( in_delayed_cldfb[i], L_FRAME48k, -gd_bits ); } - Q_sig = sub( Q_sig, 4 ); + Q_sig = sub( Q_sig, gd_bits ); num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ? CLDFB_NO_COL_MAX : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ); move32(); num_cldfb_bands = hSplitBin->hCldfbHandles->cldfbAna[0]->no_channels; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 1432c1eac..e5bf2ec99 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -7167,6 +7167,8 @@ static ivas_error renderMcToSplitBinaural( Word16 exp = *outAudio.pq_fact; move16(); CREND_HANDLE hCrend; + IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; + Word16 q_fact_orig; #ifdef SPLIT_REND_WITH_HEAD_ROT hCrend = mcInput->crendWrapper->hCrend[0]; #else @@ -7219,17 +7221,18 @@ static ivas_error renderMcToSplitBinaural( tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) ); } + FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) + { + Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] ); + } + FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ ) { /* Update head positions */ - IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; - Word16 q_fact_orig; FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ ) { - Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] ); - Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22 - q_fact_orig = combinedOrientationDataLocal.Quaternions[i].q_fact; + q_fact_orig = Quaternions_orig[i].q_fact; modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 ); /*euler*/ Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], -- GitLab From cc69948eab1d0ea64c323ee8402901d54297b499 Mon Sep 17 00:00:00 2001 From: rtyag Date: Sat, 15 Feb 2025 22:19:18 +1100 Subject: [PATCH 33/43] crash fix with 5_1 input --- lib_rend/lib_rend.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index e5bf2ec99..1c79e6f40 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -7169,11 +7169,6 @@ static ivas_error renderMcToSplitBinaural( CREND_HANDLE hCrend; IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs; Word16 q_fact_orig; -#ifdef SPLIT_REND_WITH_HEAD_ROT - hCrend = mcInput->crendWrapper->hCrend[0]; -#else - hCrend = mcInput->crendWrapper->hCrend; -#endif push_wmops( "renderMcToSplitBinaural" ); inConfig = mcInput->base.inConfig; @@ -7289,6 +7284,11 @@ static ivas_error renderMcToSplitBinaural( } ELSE { +#ifdef SPLIT_REND_WITH_HEAD_ROT + hCrend = mcInput->crendWrapper->hCrend[0]; +#else + hCrend = mcInput->crendWrapper->hCrend; +#endif /* crend processing overview: * 1. rotateFrameMc: inputBuffer to tmpRotBuffer * 2. crend_process: tmpRotBuffer to tmpRendBuffer -- GitLab From f0d096137777f9777898fae667bda7389a1a5db3 Mon Sep 17 00:00:00 2001 From: rtyag Date: Sat, 15 Feb 2025 23:48:24 +1100 Subject: [PATCH 34/43] fixes in quat shift, post renderer q fact saving --- lib_com/ivas_prot_fx.h | 9 ++++----- lib_com/ivas_rotation_com.c | 30 +++++++++++++---------------- lib_dec/ivas_binRenderer_internal.c | 10 +++++----- lib_isar/isar_stat.h | 1 + lib_isar/lib_isar_post_rend.c | 8 +++++--- lib_rend/ivas_crend.c | 5 +++-- 6 files changed, 31 insertions(+), 32 deletions(-) diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 88e8ed7ac..c3de7cee7 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -5961,11 +5961,10 @@ void modify_Quat_q_fx( ); void modify_Rmat_q_fx( - Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ - Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ - Word16 num_subframes, - Word16 q_cur, /* i : current q factor for rotation matrix */ - Word16 q_new /* i : target q factor for rotation matrix */ + Word32 Rmat_in[3][3], /* i : real-space rotation matrix for this rotation */ + Word32 Rmat_out[3][3], /* o : real-space rotation matrix for this rotation*/ + Word16 q_cur, /* i : current q factor for rotation matrix */ + Word16 q_new /* i : target q factor for rotation matrix */ ); #endif diff --git a/lib_com/ivas_rotation_com.c b/lib_com/ivas_rotation_com.c index b48fdfec2..a6d7a8ae6 100644 --- a/lib_com/ivas_rotation_com.c +++ b/lib_com/ivas_rotation_com.c @@ -116,10 +116,10 @@ void modify_Quat_q_fx( Word16 q_new /* i : quaternion describing the rotation */ ) { - out_quat->w_fx = L_shl( in_quat->w_fx, sub( q_new, in_quat->q_fact ) ); // q_new - out_quat->x_fx = L_shl( in_quat->x_fx, sub( q_new, in_quat->q_fact ) ); // q_new - out_quat->y_fx = L_shl( in_quat->y_fx, sub( q_new, in_quat->q_fact ) ); // q_new - out_quat->z_fx = L_shl( in_quat->z_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->w_fx = L_shl_sat( in_quat->w_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->x_fx = L_shl_sat( in_quat->x_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->y_fx = L_shl_sat( in_quat->y_fx, sub( q_new, in_quat->q_fact ) ); // q_new + out_quat->z_fx = L_shl_sat( in_quat->z_fx, sub( q_new, in_quat->q_fact ) ); // q_new out_quat->q_fact = q_new; return; } @@ -130,24 +130,20 @@ void modify_Quat_q_fx( * Rotation matrix q factor modification *------------------------------------------------------------------------*/ void modify_Rmat_q_fx( - Word32 Rmat_in[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* i : real-space rotation matrix for this rotation */ - Word32 Rmat_out[MAX_PARAM_SPATIAL_SUBFRAMES][3][3], /* o : real-space rotation matrix for this rotation*/ - Word16 num_subframes, - Word16 q_cur, /* i : current q factor for rotation matrix */ - Word16 q_new /* i : target q factor for rotation matrix */ + Word32 Rmat_in[3][3], /* i : real-space rotation matrix for this rotation */ + Word32 Rmat_out[3][3], /* o : real-space rotation matrix for this rotation*/ + Word16 q_cur, /* i : current q factor for rotation matrix */ + Word16 q_new /* i : target q factor for rotation matrix */ ) { - Word16 i, j, k; + Word16 j, k; - FOR( i = 0; i < num_subframes; i++ ) + FOR( j = 0; j < 3; j++ ) { - FOR( j = 0; j < 3; j++ ) + FOR( k = 0; k < 3; k++ ) { - FOR( k = 0; k < 3; k++ ) - { - Rmat_out[i][j][k] = L_shl( Rmat_in[i][j][k], sub( q_new, q_cur ) ); - move32(); - } + Rmat_out[j][k] = L_shl( Rmat_in[j][k], sub( q_new, q_cur ) ); + move32(); } } return; diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 97d7905f3..eb0a081f4 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1956,7 +1956,7 @@ void ivas_binRenderer_fx( IF( GT_16( pMultiBinPoseData->num_poses, 1 ) ) { IVAS_QUATERNION Quaternions_abs, Quaternions_ref, Quaternions_ref2; - Word32 Rmat_local[MAX_PARAM_SPATIAL_SUBFRAMES][3][3]; + Word32 Rmat_local[3][3]; Word16 q_fact_orig; IF( hCombinedOrientationData && hBinRenderer->rotInCldfb ) @@ -2000,17 +2000,17 @@ void ivas_binRenderer_fx( modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig ); - QuatToRotMat_fx( Quaternions_abs, Rmat_local[0] ); + QuatToRotMat_fx( Quaternions_abs, Rmat_local ); - modify_Rmat_q_fx( Rmat_local, Rmat_local, 1, sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); + modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); if ( hBinRenderer->hInputSetup->is_loudspeaker_setup ) { - rotateFrame_sd_cldfb_fixed( Rmat_local[0], RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); + rotateFrame_sd_cldfb_fixed( Rmat_local, RealBuffer_fx, ImagBuffer_fx, hBinRenderer->hInputSetup, hBinRenderer->hEFAPdata, numTimeSlots, hBinRenderer->conv_band ); } else { - rotateFrame_shd_cldfb( RealBuffer_fx, ImagBuffer_fx, Rmat_local[0], hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 ); + rotateFrame_shd_cldfb( RealBuffer_fx, ImagBuffer_fx, Rmat_local, hBinRenderer->hInputSetup->nchan_out_woLFE, numTimeSlots, 3 ); } FOR( chIdx = 0; chIdx < BINAURAL_CHANNELS; chIdx++ ) diff --git a/lib_isar/isar_stat.h b/lib_isar/isar_stat.h index 228bc94df..171f82022 100644 --- a/lib_isar/isar_stat.h +++ b/lib_isar/isar_stat.h @@ -237,6 +237,7 @@ typedef struct ISAR_BIN_HR_SPLIT_LCLD_DEC_HANDLE hSplitBinLCLDDec; int16_t first_good_frame_received; ISAR_LC3PLUS_DEC_HANDLE hLc3plusDec; + Word16 Q_last; } ISAR_SPLIT_POST_REND_WRAPPER; diff --git a/lib_isar/lib_isar_post_rend.c b/lib_isar/lib_isar_post_rend.c index c59159061..7cfd50e49 100644 --- a/lib_isar/lib_isar_post_rend.c +++ b/lib_isar/lib_isar_post_rend.c @@ -1486,6 +1486,7 @@ static ivas_error renderSplitBinauralWithPostRot( { isar_splitBinLCLDDecProcess( hSplitBin->hSplitBinLCLDDec, &bits, Cldfb_RealBuffer_Binaural_fx, Cldfb_ImagBuffer_Binaural_fx, &Q_cldfb_final[sf_idx], SplitRendBFI ); // Q_cldfb_final + hSplitBin->Q_last = Q_cldfb_final[sf_idx]; /* copy data over to 5ms buffer */ FOR( chnlIdx = 0; chnlIdx < BINAURAL_CHANNELS; ++chnlIdx ) { @@ -1526,6 +1527,7 @@ static ivas_error renderSplitBinauralWithPostRot( { return error; } + hSplitBin->Q_last = Q_out[sf_idx][0]; /* cache the remaining 15ms */ splitBinInput->numCachedSamples = numSamplesPerChannelCacheSize; @@ -1540,7 +1542,7 @@ static ivas_error renderSplitBinauralWithPostRot( { Word16 readOffset = sub( numColPerChannelCacheSize, splitBinInput->numCachedSamples ); readPtr_fx = splitBinInput->bufferData_fx; - Q_cldfb_final[sf_idx] = Q_cldfb_final[sf_idx - 1]; + Q_cldfb_final[sf_idx] = hSplitBin->Q_last; isPostRendInputCldfb = 1; readPtr_fx += 2 * readOffset * CLDFB_NO_CHANNELS_MAX * BINAURAL_CHANNELS; @@ -1566,8 +1568,8 @@ static ivas_error renderSplitBinauralWithPostRot( Word16 readOffset = numSamplesPerChannelCacheSize - splitBinInput->numCachedSamples; mvl2l( splitBinInput->bufferData_fx + readOffset, &tmpCrendBuffer_fx[0][sf_idx * outBufNumSamplesPerChannel], outBufNumSamplesPerChannel ); mvl2l( splitBinInput->bufferData_fx + readOffset + numSamplesPerChannelCacheSize, &tmpCrendBuffer_fx[1][sf_idx * outBufNumSamplesPerChannel], outBufNumSamplesPerChannel ); - Q_out[sf_idx][0] = Q_out[sf_idx - 1][0]; - Q_out[sf_idx][1] = Q_out[sf_idx - 1][1]; + Q_out[sf_idx][0] = hSplitBin->Q_last; + Q_out[sf_idx][1] = hSplitBin->Q_last; splitBinInput->numCachedSamples -= outBufNumSamplesPerChannel; } } diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index a974364f4..1c77b9dcc 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -2519,8 +2519,8 @@ ivas_error ivas_rend_crendProcessSplitBin( move32(); modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Quaternions_orig[i].q_fact ); QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx[i], combinedOrientationDataLocal.Rmat_fx[i], sub( shl( Quaternions_orig[i].q_fact, 1 ), 32 ), Q30 ); } - modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx, combinedOrientationDataLocal.Rmat_fx, MAX_PARAM_SPATIAL_SUBFRAMES, sub( shl( Quaternions_orig[0].q_fact, 1 ), 32 ), Q30 ); /* render inplace to first two channels of tmpInputBuffer */ @@ -2692,8 +2692,9 @@ ivas_error ivas_rend_crendProcessSubframesSplitBin( &combinedOrientationDataLocal.Quaternions[i] ); modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Quaternions_orig[i].q_fact ); QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx[i], combinedOrientationDataLocal.Rmat_fx[i], sub( shl( Quaternions_orig[i].q_fact, 1 ), 32 ), Q30 ); } - modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx, combinedOrientationDataLocal.Rmat_fx, MAX_PARAM_SPATIAL_SUBFRAMES, sub( shl( Quaternions_orig[0].q_fact, 1 ), 32 ), Q30 ); + pCombinedOrientationDataLocal = &combinedOrientationDataLocal; move32(); -- GitLab From a145e762d148ede33e8cb20bd348f03db822625d Mon Sep 17 00:00:00 2001 From: rtyag Date: Sun, 16 Feb 2025 00:59:07 +1100 Subject: [PATCH 35/43] pcm out fix, 5ms lcld framing fix --- lib_isar/isar_lcld_decoder.c | 2 +- lib_isar/lib_isar_pre_rend.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib_isar/isar_lcld_decoder.c b/lib_isar/isar_lcld_decoder.c index 2695b397d..9b70c1515 100644 --- a/lib_isar/isar_lcld_decoder.c +++ b/lib_isar/isar_lcld_decoder.c @@ -996,7 +996,7 @@ Word32 DecodeLCLDFrame( *Q_out = Q; FOR( n = 0; n < psLCLDDecoder->iChannels; n++ ) { - FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ ) + FOR( i = 0; i < psLCLDDecoder->iNumBlocks; i++ ) { FOR( j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index f528d0348..5ebfd8e61 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -374,6 +374,8 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( #endif codec_frame_size_ms, pBits, max_bands, pOutput_fx, Q_out[0], low_res_pre_rend_rot, pcm_out_flag, ro_md_flag ); + Q_out[1] = Q_out[0]; + move16(); pop_wmops(); return error; } -- GitLab From fbfeb33385a0eb76ff04df482c65291db778ba6c Mon Sep 17 00:00:00 2001 From: rtyag Date: Mon, 17 Feb 2025 20:15:08 +1100 Subject: [PATCH 36/43] addition of -p BASOP to instrumentation job --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4fe5ec338..16563bf57 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -896,7 +896,7 @@ build-codec-linux-instrumented-make: script: - *print-common-info - *update-scripts-repo - - bash scripts/prepare_instrumentation.sh -m MEM_ONLY + - bash scripts/prepare_instrumentation.sh -m MEM_ONLY -p BASOP - make -j -C $INSTR_DIR -- GitLab From 1a3093376b1cb4217bcf558fd2dbe1cc9ee31fb8 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 19 Feb 2025 10:43:52 +1100 Subject: [PATCH 37/43] fix for lc3plus sanitizer --- lib_isar/isar_lc3plus_enc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib_isar/isar_lc3plus_enc.c b/lib_isar/isar_lc3plus_enc.c index f6bb0284d..bf76e2e59 100644 --- a/lib_isar/isar_lc3plus_enc.c +++ b/lib_isar/isar_lc3plus_enc.c @@ -147,6 +147,7 @@ ivas_error ISAR_LC3PLUS_ENC_Open( #endif ( *handle )->pcm_conversion_buffer = NULL; + ( *handle )->scratch = NULL; ( *handle )->num_encs = 0; if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL ) { -- GitLab From 100b1737cfdef8feb539912f3a4a8a616f1a3160 Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 20 Feb 2025 11:41:36 +1100 Subject: [PATCH 38/43] WMOPS SKIP for two UWords32 () lines --- .gitlab-ci.yml | 2 +- lib_isar/isar_lcld_decoder.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 16563bf57..4fe5ec338 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -896,7 +896,7 @@ build-codec-linux-instrumented-make: script: - *print-common-info - *update-scripts-repo - - bash scripts/prepare_instrumentation.sh -m MEM_ONLY -p BASOP + - bash scripts/prepare_instrumentation.sh -m MEM_ONLY - make -j -C $INSTR_DIR diff --git a/lib_isar/isar_lcld_decoder.c b/lib_isar/isar_lcld_decoder.c index 9b70c1515..371aee854 100644 --- a/lib_isar/isar_lcld_decoder.c +++ b/lib_isar/isar_lcld_decoder.c @@ -1860,8 +1860,10 @@ static Word32 ReadLCLDData_fx( #ifdef USE_DEMOD_TABLES const int32_t( *paiDemodTable )[2] = NULL; #endif +#define WMC_TOOL_SKIP pauiHuffmanTable = (const UWord32( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[iAlloc]; pauiHuffmanTableDPCM = (const UWord32( * )[HUFF_DEC_TABLE_SIZE]) c_apauiHuffDecTables[ALLOC_TABLE_SIZE + iAlloc]; +#undef WMC_TOOL_SKIP #ifdef USE_DEMOD_TABLES paiDemodTable = c_apaiDemodTables[iAlloc]; #endif -- GitLab From 56ef608aae1d8760768844d3b9b7e3774ecc663a Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 20 Feb 2025 17:04:29 +1100 Subject: [PATCH 39/43] setting lc3plus scrtach buffer to NULL before malloc --- lib_isar/isar_lc3plus_dec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib_isar/isar_lc3plus_dec.c b/lib_isar/isar_lc3plus_dec.c index 1c63158b3..2aec77746 100644 --- a/lib_isar/isar_lc3plus_dec.c +++ b/lib_isar/isar_lc3plus_dec.c @@ -116,6 +116,7 @@ ivas_error ISAR_LC3PLUS_DEC_Open( ( *handle )->handles = NULL; ( *handle )->selective_decoding_states = NULL; ( *handle )->bitstream_caches = NULL; + ( *handle )->scratch = NULL; if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_DEC_HANDLE ) ) ) == NULL ) { -- GitLab From 83f0fa157e3bffb2be6a0706fa358a65c258d7bd Mon Sep 17 00:00:00 2001 From: rtyag Date: Mon, 24 Feb 2025 10:39:56 +1100 Subject: [PATCH 40/43] bug fix for cases when rotation happens in DirAC --- lib_dec/ivas_binRenderer_internal.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 0b079177b..bc428106c 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1956,7 +1956,7 @@ void ivas_binRenderer_fx( { IVAS_QUATERNION Quaternions_abs, Quaternions_ref, Quaternions_ref2; Word32 Rmat_local[3][3]; - Word16 q_fact_orig; + Word16 q_fact_orig, extra_shift = 0; IF( hCombinedOrientationData && hBinRenderer->rotInCldfb ) { @@ -1972,6 +1972,7 @@ void ivas_binRenderer_fx( Quaternions_ref2.x_fx = 0; Quaternions_ref2.y_fx = 0; Quaternions_ref2.z_fx = 0; + extra_shift = 1; } ELSE { @@ -2028,9 +2029,9 @@ void ivas_binRenderer_fx( { FOR( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ ) { - Cldfb_RealBuffer_Binaural_fx[pos_idx][i][j][k] = W_extract_l( W_shr( Cldfb_RealBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 + Cldfb_RealBuffer_Binaural_fx[pos_idx][i][j][k] = W_extract_l( W_shr( Cldfb_RealBuffer_Binaural_64fx[i][j][k], 29 - extra_shift ) ); //(*Q_in + 29) - 29 move32(); - Cldfb_ImagBuffer_Binaural_fx[pos_idx][i][j][k] = W_extract_l( W_shr( Cldfb_ImagBuffer_Binaural_64fx[i][j][k], 29 ) ); //(*Q_in + 29) - 29 + Cldfb_ImagBuffer_Binaural_fx[pos_idx][i][j][k] = W_extract_l( W_shr( Cldfb_ImagBuffer_Binaural_64fx[i][j][k], 29 - extra_shift ) ); //(*Q_in + 29) - 29 move32(); } } -- GitLab From afde1c1eb2ea21dbd04d0cde5e68be5860a30de6 Mon Sep 17 00:00:00 2001 From: rtyag Date: Mon, 24 Feb 2025 12:30:15 +1100 Subject: [PATCH 41/43] cldfb in lc3plus coding, bug fix for q fact of TD in to lc3plus --- lib_isar/lib_isar_pre_rend.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 5ebfd8e61..3b19c1ad0 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -474,28 +474,40 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( num_slots = shr( tmp, sub( 15, tmp_e ) ); // Q0 // num_slots = (Word16) CLDFB_NO_COL_MAX * ivas_fs / 20; /* CLDFB synthesis of main pose */ - FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - Word32 *Cldfb_In_BinReal_p_fx[CLDFB_NO_COL_MAX]; - Word32 *Cldfb_In_BinImag_p_fx[CLDFB_NO_COL_MAX]; q1 = 31; q2 = 31; move16(); move16(); - FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 ); - q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 ); + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + q1 = s_min( getScaleFactor32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q1 ); + q2 = s_min( getScaleFactor32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX ), q2 ); + } } + q_final = s_min( q1, q2 ); q_final = s_min( add( Q_buff_re, q_final ), add( Q_buff_im, q_final ) ); q_final = sub( q_final, 3 ); // guard bits q_final = s_min( q_final, Q25 ); - FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) { - Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); - Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + { + Scale_sig32( Cldfb_In_BinReal_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_re ) ); + Scale_sig32( Cldfb_In_BinImag_fx[ch][j], CLDFB_NO_CHANNELS_MAX, sub( q_final, Q_buff_im ) ); + } } + } + + FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + Word32 *Cldfb_In_BinReal_p_fx[CLDFB_NO_COL_MAX]; + Word32 *Cldfb_In_BinImag_p_fx[CLDFB_NO_COL_MAX]; + FOR( slot_idx = 0; slot_idx < num_slots; slot_idx++ ) { @@ -514,6 +526,7 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( hSplitBin->hCldfbHandles->cldfbSyn[ch]->Q_cldfb_state = Q_out[ch]; move16(); } + assert( Q_out[0] == Q_out[1] ); #ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS available_bits = ( SplitRendBitRate / FRAMES_PER_SEC ) - pBits->bits_written; -- GitLab From 06e004881ce5add9c083ad74a8cf4d539b85e940 Mon Sep 17 00:00:00 2001 From: rtyag Date: Tue, 25 Feb 2025 21:13:26 +1100 Subject: [PATCH 42/43] rotation matrix q factor setting to Q30 --- lib_com/options.h | 16 +++++++++++----- lib_isar/isar_splitRendererPre.c | 4 ++-- lib_rend/ivas_dirac_dec_binaural_functions.c | 2 ++ lib_rend/lib_rend.c | 2 ++ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 90237fa34..51beb86ef 100755 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -125,11 +125,6 @@ #define FIX_ISSUE_1187 /* Ittiam: Fix for issue 1187: Assertion error observed in evs_enc_fx (with option stereo_dmx_evs) from bass_pf_enc_fx function*/ #define FIX_ISSUE_1186 /* Ittiam: Fix for Issue 1186: Energy/scaling issue for ISM-1 at all bitrates */ #define FIX_ISSUE_1165 /* Ittiam: Fix for issue 1165: Assertion in lpc2lsp_fx for OMASA LTV input */ -#define SPLIT_REND_WITH_HEAD_ROT /* Dlb,FhG: Split Rendering contributions 21 and 35 */ -#ifdef SPLIT_REND_WITH_HEAD_ROT -#define SPLIT_REND_POSE_CORRECTION_UNUSED_BITS -#define ISAR_BITSTREAM_UPDATE_LC3PLUS /* FhG: Multiple improvements to the ISAR bitstream when LC3plus is used. See MR 1456 for details. */ -#endif #define FIX_ISSUE_1185 /* Ittiam: Fix for issue 1185: Assertion in ivas_dirac_dec_binaural_internal_fx() for crash in decoder in fft30_with_cmplx_data()*/ #define FIX_ISSUE_1209 /* Ittiam: Fix for issue 1209: Assertion exit in BASOP encoder (stereo_dmx_evs)*/ #define FIX_ISSUE_1218 /* Ittiam: Fix for issue 1218: Assert in stereo_dft_generate_comfort_noise_fx of BASOP decoder with BASOP MASA DTX bitstream at 32 kbps*/ @@ -169,4 +164,15 @@ #define FIX_ISSUE_1247 #define NONBE_FIX_1087_OOB_SBA_DTX_RS /* VA: issue 1087: Extend the length of the buffer for MCT decoding to avoid out-of-bound writing in SBA SID bitrate switching decoding */ #define FIX_1285_DECODER_CRASH + +/* #################### Start BASOP porting switches ############################ */ + +#define SPLIT_REND_WITH_HEAD_ROT /* Dlb,FhG: Split Rendering contributions 21 and 35 */ +#ifdef SPLIT_REND_WITH_HEAD_ROT +#define SPLIT_REND_POSE_CORRECTION_UNUSED_BITS +#define ISAR_BITSTREAM_UPDATE_LC3PLUS /* FhG: Multiple improvements to the ISAR bitstream when LC3plus is used. See MR 1456 for details. */ +#endif + +/* #################### End BASOP porting switches ############################ */ + #endif diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 306753bd6..8dd0cdf95 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -944,7 +944,7 @@ static void isar_split_rend_quant_md_fx( { FOR( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) { - quant_val = L_sub( hMd->pred_mat_re_fx[ch1][ch2], L_shr_r( ( ch1 == ch2 ) ? ONE_IN_Q31 : 0, sub( Q31, Q_frame ) ) ); + quant_val = L_sub_sat( hMd->pred_mat_re_fx[ch1][ch2], L_shr_r( ( ch1 == ch2 ) ? ONE_IN_Q31 : 0, sub( Q31, Q_frame ) ) ); quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PRED_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( quant_val, L_shr_r( ISAR_SPLIT_REND_PRED_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); hMd->pred_mat_re_idx[ch1][ch2] = (Word16) L_shr_r( Mpy_32_32( onebyquantstep, quant_val ), sub( Q_frame, 5 ) ); // Q25*Q26 = Q20 -> Q16 -> Q0 } @@ -972,7 +972,7 @@ static void isar_split_rend_quant_md_fx( { for ( ch2 = 0; ch2 < BINAURAL_CHANNELS; ch2++ ) { - quant_val = L_sub( hMd->pred_mat_re_fx[ch1][ch2], L_shr_r( fix_pos_rot_mat[ch1][ch2], sub( Q31, Q_frame ) ) ); + quant_val = L_sub_sat( hMd->pred_mat_re_fx[ch1][ch2], L_shr_r( fix_pos_rot_mat[ch1][ch2], sub( Q31, Q_frame ) ) ); quant_val = L_min( L_shr_r( ISAR_SPLIT_REND_PRED_MAX_VAL_Q30, sub( Q30, Q_frame ) ), L_max( quant_val, L_shr_r( ISAR_SPLIT_REND_PRED_MIN_VAL_Q30, sub( Q30, Q_frame ) ) ) ); hMd->pred_mat_re_idx[ch1][ch2] = (Word16) L_shr_r( Mpy_32_32( onebyquantstep, quant_val ), sub( Q_frame, 5 ) ); // Q25*Q26 = Q20 -> Q16 -> Q0 diff --git a/lib_rend/ivas_dirac_dec_binaural_functions.c b/lib_rend/ivas_dirac_dec_binaural_functions.c index 51dafc8dd..a88ea9375 100644 --- a/lib_rend/ivas_dirac_dec_binaural_functions.c +++ b/lib_rend/ivas_dirac_dec_binaural_functions.c @@ -1179,6 +1179,7 @@ static void ivas_dirac_dec_binaural_internal_fx( Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot ); modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact ); QuatToRotMat_fx( Quaternions_rot, Rmat_local ); + modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( Quaternions_ref->q_fact, 1 ), 32 ), Q30 ); hDiracDecBin = st_ivas->hDiracDecBin[pos_idx]; assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" ); @@ -6862,6 +6863,7 @@ static void ivas_masa_ext_rend_parambin_internal_fx( Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot ); modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact ); QuatToRotMat_fx( Quaternions_rot, Rmat_local ); + modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( Quaternions_ref->q_fact, 1 ), 32 ), Q30 ); hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx]; assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" ); diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index f3dfe51e9..a8ca4528c 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -7272,6 +7272,7 @@ static ivas_error renderMcToSplitBinaural( Copy_Quat_fx( &Quaternions_abs, &combinedOrientationDataLocal.Quaternions[i] ); QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx[i], combinedOrientationDataLocal.Rmat_fx[i], sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); } IF( EQ_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) @@ -7595,6 +7596,7 @@ static ivas_error renderSbaToMultiBinaural( Copy_Quat_fx( &Quaternions_abs, &combinedOrientationDataLocal.Quaternions[i] ); QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] ); + modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx[i], combinedOrientationDataLocal.Rmat_fx[i], sub( shl( q_fact_orig, 1 ), 32 ), Q30 ); } /* copy input for in-place rotation */ -- GitLab From 9173eff44984352693077f63909f1e7cbb94c67d Mon Sep 17 00:00:00 2001 From: rtyag Date: Thu, 27 Feb 2025 20:07:44 +1100 Subject: [PATCH 43/43] fix for SPLIT PCM output cases, save 32 bit bin outputs --- lib_dec/ivas_jbm_dec.c | 13 ++++++------- lib_dec/ivas_stat_dec.h | 1 + lib_dec/lib_dec_fx.c | 25 +++++++++---------------- lib_isar/isar_splitRendererPre.c | 4 ++-- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index cc31e1412..5ad45a282 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -2686,14 +2686,13 @@ ivas_error ivas_jbm_dec_render_fx( #ifdef SPLIT_REND_WITH_HEAD_ROT IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) { - nchan_out_syn_output = i_mult( BINAURAL_CHANNELS, st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); - move16(); - } - ELSE - { - nchan_out_syn_output = nchan_out; - move16(); + FOR( i = 0; i < st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses * BINAURAL_CHANNELS; i++ ) + { + Copy32( p_output_fx[i], st_ivas->hSplitBinRend->hMultiBinCldfbData->output_fx[i], *nSamplesRendered ); + } } + nchan_out_syn_output = nchan_out; + move16(); IF( st_ivas->hDecoderConfig->Opt_Limiter ) #endif diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 2d71508f7..c9942de12 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -896,6 +896,7 @@ typedef struct { Word32 Cldfb_RealBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural_fx[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 output_fx[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; } ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA, *ISAR_DEC_SPLIT_REND_MULTI_BIN_CLDFB_DATA_HANDLE; diff --git a/lib_dec/lib_dec_fx.c b/lib_dec/lib_dec_fx.c index 9917b6f40..025b407d1 100644 --- a/lib_dec/lib_dec_fx.c +++ b/lib_dec/lib_dec_fx.c @@ -1324,8 +1324,6 @@ IVAS_DEC_GetSplitBinauralBitstream( AUDIO_CONFIG output_config; Word32 output_Fs; Word32 *pOutput[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; - Word32 output[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; - Word16 pcmBuf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES * L_FRAME48k]; Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; FOR( Word32 i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) @@ -1413,24 +1411,15 @@ IVAS_DEC_GetSplitBinauralBitstream( /* Decode and render */ - if ( ( error = IVAS_DEC_GetSamples( hIvasDec, numSamplesPerChannelToDecode, pcmBuf, nOutSamples, needNewFrame ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_GetSamples( hIvasDec, numSamplesPerChannelToDecode, pcmBuf_out, nOutSamples, needNewFrame ) ) != IVAS_ERR_OK ) { return error; } - /* change buffer layout */ - FOR( i = 0; i < numSamplesPerChannelToDecode; ++i ) - { - FOR( j = 0; j < BINAURAL_CHANNELS * numPoses; ++j ) - { - output[j][i] = (Word32) pcmBuf[add( i_mult( i, i_mult( BINAURAL_CHANNELS, numPoses ) ), j )]; - move32(); - } - } FOR( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) { - pOutput[i] = output[i]; + pOutput[i] = hSplitBinRend->hMultiBinCldfbData->output_fx[i]; move32(); } @@ -1510,7 +1499,7 @@ IVAS_DEC_GetSplitBinauralBitstream( scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff ); } } - Q_buff = Q_buff + Q6; + Q_buff = add( Q_buff, Q6 ); IF( NE_16( td_input, 0 ) ) { @@ -1521,14 +1510,17 @@ IVAS_DEC_GetSplitBinauralBitstream( FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { - Q_out[0] = s_min( Q_out[0], L_norm_arr( output[i], L_FRAME48k ) ); + Q_out[0] = s_min( Q_out[0], L_norm_arr( pOutput[i], L_FRAME48k ) ); } FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i ) { - scale_sig32( output[i], L_FRAME48k, Q_out[0] ); + scale_sig32( pOutput[i], L_FRAME48k, Q_out[0] ); } + Q_out[0] = add( Q_out[0], Q11 ); + Q_out[1] = Q_out[0]; } + if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( &hSplitBinRend->splitrend, Quaternion, st_ivas->hRenderConfig->split_rend_config.splitRendBitRate, @@ -1546,6 +1538,7 @@ IVAS_DEC_GetSplitBinauralBitstream( return error; } + /* convert to int16 with limiting for BINAURAL_SPLIT_PCM */ IF( pcm_out_flag ) { diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 8dd0cdf95..6cb44b015 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -3250,7 +3250,7 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( /*scaling to max Q*/ Word16 scale_factor = 31; move32(); - FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ ) { FOR( Word16 j = 0; j < CLDFB_NO_COL_MAX; j++ ) { @@ -3258,7 +3258,7 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( } } scale_factor = sub( scale_factor, 2 ); - FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ ) + FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ ) { FOR( Word16 j = 0; j < CLDFB_NO_COL_MAX; j++ ) { -- GitLab